Implement match logic and syntax

This commit is contained in:
Jeff 2023-12-11 10:18:46 -05:00
parent 99338dedc5
commit 06da345333
6 changed files with 5380 additions and 5249 deletions

12
examples/match.ds Normal file
View File

@ -0,0 +1,12 @@
foo_or_bar = match (random_boolean) {
true => "foo"
false => "bar"
}
num = match (random_integer) {
1 => "one",
2 => { "two" },
* => "neither",
}
[foo_or_bar, num]

View File

@ -13,6 +13,7 @@ use crate::{AbstractTree, Error, Expression, Map, Result, Statement, Type, Value
pub struct Match {
matcher: Expression,
options: Vec<(Expression, Statement)>,
fallback: Option<Box<Statement>>,
}
impl AbstractTree for Match {
@ -24,24 +25,37 @@ impl AbstractTree for Match {
let mut options = Vec::new();
let mut previous_expression = None;
let mut next_statement_is_fallback = false;
let mut fallback = None;
for index in 2..node.child_count() {
let child = node.child(index).unwrap();
if child.kind() == "*" {
next_statement_is_fallback = true;
}
if child.kind() == "expression" {
previous_expression = Some(Expression::from_syntax_node(source, child, context)?);
}
if child.kind() == "statement" {
if let Some(expression) = &previous_expression {
let statement = Statement::from_syntax_node(source, child, context)?;
let statement = Statement::from_syntax_node(source, child, context)?;
if next_statement_is_fallback {
fallback = Some(Box::new(statement));
next_statement_is_fallback = false;
} else if let Some(expression) = &previous_expression {
options.push((expression.clone(), statement));
}
}
}
Ok(Match { matcher, options })
Ok(Match {
matcher,
options,
fallback,
})
}
fn run(&self, source: &str, context: &Map) -> Result<Value> {
@ -55,7 +69,11 @@ impl AbstractTree for Match {
}
}
Ok(Value::Empty)
if let Some(fallback) = &self.fallback {
fallback.run(source, context)
} else {
Ok(Value::Empty)
}
}
fn expected_type(&self, _context: &Map) -> Result<Type> {

View File

@ -1,4 +1,4 @@
use serde::{ser::SerializeMap, Deserialize, Serialize};
use serde::{ser::SerializeMap, Serialize};
use std::{
cmp::Ordering,
collections::BTreeMap,

View File

@ -285,9 +285,13 @@ module.exports = grammar({
'{',
repeat1(
seq(
$.expression,
choice(
$.expression,
'*',
),
'=>',
$.statement,
optional(','),
),
),
'}',

View File

@ -896,8 +896,17 @@
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "*"
}
]
},
{
"type": "STRING",
@ -906,6 +915,18 @@
{
"type": "SYMBOL",
"name": "statement"
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
}

File diff suppressed because it is too large Load Diff