1
0

Begin match implementation

This commit is contained in:
Jeff 2023-10-30 22:12:03 -04:00
parent 9c565e810e
commit 6b916da62d
12 changed files with 7629 additions and 6517 deletions

2
Cargo.lock generated
View File

@ -459,7 +459,7 @@ dependencies = [
[[package]] [[package]]
name = "dust-lang" name = "dust-lang"
version = "0.3.4" version = "0.3.5"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"async-std", "async-std",

View File

@ -21,16 +21,16 @@ remove_card = function <opponent_card> {
} }
make_guess = function <current_room> { make_guess = function <current_room> {
if ((length suspects) == 1) if (length suspects) == 1
&& ((length rooms) == 1) && (length rooms) == 1
&& ((length weapons) == 1) && (length weapons) == 1
{ {
(output 'It was ' (output 'It was '
+ suspects.{0} + suspects:0
+ ' in the ' + ' in the '
+ rooms.{0} + rooms:0
+ ' with the ' + ' with the '
+ weapons.{0} + weapons:0
+ '!') + '!')
} else { } else {
(output 'I accuse ' (output 'I accuse '

View File

@ -1,6 +1,6 @@
list = [1 2 3] list = [1 2 3]
async for i in list { for i in list {
i += 1 i += 1
(output i) (output i)
} }

View File

@ -6,8 +6,8 @@ func = function <> {
x x
} }
assert_equal("foo", (func)) (assert_equal "foo", (func))
assert_equal("bar", x) (assert_equal "bar", x)
# For Loop # For Loop
x = 42 x = 42
@ -16,7 +16,7 @@ for number in [1 2 3] {
x += number x += number
} }
assert_equal(48, x) (assert_equal 48, x)
# Async Loops # Async Loops
@ -30,8 +30,8 @@ transform number in y {
x = 1000 x = 1000
} }
assert_equal([43, 44, 45], y) (assert_equal [43, 44, 45], y)
assert_equal(42, x) (assert_equal 42, x)
## Filter Loop ## Filter Loop
@ -43,8 +43,8 @@ transform number in y {
x = 1000 x = 1000
} }
assert_equal([43, 44, 45], y) (assert_equal [43, 44, 45], y)
assert_equal(42, x) (assert_equal 42, x)
## Filter Loop ## Filter Loop
@ -56,5 +56,5 @@ filter number in y {
x = 1000 x = 1000
} }
assert_equal([43, 44, 45], y) (assert_equal [43, 44, 45], y)
assert_equal(42, x) (assert_equal 42, x)

View File

@ -1,5 +1,5 @@
data = (from_json (read "examples/assets/jq_data.json")) data = (from_json (read "examples/assets/jq_data.json"))
transform item in data { transform item in data {
item.{commit}.{committer}.{name} item:commit:committer:name
} }

View File

@ -1,3 +1,4 @@
use async_std::task;
use rayon::prelude::*; use rayon::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tree_sitter::Node; use tree_sitter::Node;
@ -6,48 +7,78 @@ use crate::{AbstractTree, Error, Expression, Identifier, Item, List, Map, Result
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)]
pub struct Filter { pub struct Filter {
identifier: Identifier, count: Option<Expression>,
expression: Expression, item_id: Identifier,
item: Item, collection: Expression,
predicate: Item,
} }
impl AbstractTree for Filter { impl AbstractTree for Filter {
fn from_syntax_node(source: &str, node: Node) -> Result<Self> { fn from_syntax_node(source: &str, node: Node) -> Result<Self> {
let identifier_node = node.child(1).unwrap(); let count = if let Some(node) = node.child_by_field_name("count") {
Some(Expression::from_syntax_node(source, node)?)
} else {
None
};
let identifier_node = node.child_by_field_name("item_id").unwrap();
let identifier = Identifier::from_syntax_node(source, identifier_node)?; let identifier = Identifier::from_syntax_node(source, identifier_node)?;
let expression_node = node.child(3).unwrap(); let expression_node = node.child_by_field_name("collection").unwrap();
let expression = Expression::from_syntax_node(source, expression_node)?; let expression = Expression::from_syntax_node(source, expression_node)?;
let item_node = node.child(5).unwrap(); let item_node = node.child_by_field_name("predicate").unwrap();
let item = Item::from_syntax_node(source, item_node)?; let item = Item::from_syntax_node(source, item_node)?;
Ok(Filter { Ok(Filter {
identifier, count,
expression, item_id: identifier,
item, collection: expression,
predicate: item,
}) })
} }
fn run(&self, source: &str, context: &mut Map) -> Result<Value> { fn run(&self, source: &str, context: &mut Map) -> Result<Value> {
let value = self.expression.run(source, context)?; let value = self.collection.run(source, context)?;
let values = value.as_list()?.items(); let values = value.as_list()?.items();
let key = self.identifier.inner(); let count = if let Some(expression) = &self.count {
let new_values = List::new(); Some(expression.run(source, context)?.as_integer()? as usize)
} else {
None
};
let key = self.item_id.inner();
let new_values = match count {
Some(count) => List::with_capacity(count),
None => List::new(),
};
values.par_iter().try_for_each(|value| { async {};
let mut context = Map::new();
context.variables_mut().insert(key.clone(), value.clone()); for value in values.clone().into_iter() {
task::spawn(async {
let new_values = new_values.clone();
if let Some(max) = count {
if values.len() == max {
return;
}
}
let should_include = self.item.run(source, &mut context)?.as_boolean()?; let mut context = Map::new();
if should_include { context.variables_mut().insert(key.clone(), value.clone());
new_values.items_mut().push(value.clone());
}
Ok::<(), Error>(()) let predicate_run = self.predicate.run(source, &mut context);
})?; let should_include = if let Ok(value) = predicate_run {
value.as_boolean().unwrap_or_default()
} else {
return;
};
if should_include {
new_values.items_mut().push(value);
}
});
}
Ok(Value::List(new_values)) Ok(Value::List(new_values))
} }

View File

@ -2,7 +2,7 @@
Filter Loop Filter Loop
================== ==================
filter i in [1, 2, 3] { filter 1 i in [1, 2, 3] {
i <= 1 i <= 1
} }
@ -12,6 +12,9 @@ filter i in [1, 2, 3] {
(item (item
(statement (statement
(filter (filter
(expression
(value
(integer)))
(identifier) (identifier)
(expression (expression
(value (value

View File

@ -0,0 +1,126 @@
==================
Simple Match
==================
match 1 {
3 => 'foo'
2 => 'bar'
1 => 42
}
---
(root
(item
(statement
(match
(expression
(value
(integer)))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(string)))))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(string)))))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(integer)))))))))
==================
Nested Matches
==================
match 1 {
3 => match true {
true => match (random_integer) {
0 => 42
9 => 'foo'
}
false => 0
}
2 => 'bar'
1 => 42
}
---
(root
(item
(statement
(match
(expression
(value
(integer)))
(expression
(value
(integer)))
(item
(statement
(match
(expression
(value
(boolean)))
(expression
(value
(boolean)))
(item
(statement
(match
(expression
(tool))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(integer)))))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(string))))))))
(expression
(value
(boolean)))
(item
(statement
(expression
(value
(integer))))))))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(string)))))
(expression
(value
(integer)))
(item
(statement
(expression
(value
(integer)))))))))

View File

@ -22,6 +22,7 @@ module.exports = grammar({
$.filter, $.filter,
$.find, $.find,
$.remove, $.remove,
$.match,
)), )),
comment: $ => seq(/[#]+.*/), comment: $ => seq(/[#]+.*/),
@ -54,21 +55,19 @@ module.exports = grammar({
$.map, $.map,
), ),
_numeric: $ => token(repeat1( integer: $ => prec.left(token(seq(
choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') optional('-'),
)), repeat1(
choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')
),
))),
integer: $ => prec.left(seq( float: $ => prec.left(token(seq(
optional(token.immediate('-')), optional('-'),
$._numeric, repeat1(choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')),
)), '.',
repeat1(choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')),
float: $ => prec.left(seq( ))),
optional(token.immediate('-')),
$._numeric,
token.immediate('.'),
$._numeric,
)),
string: $ => /("[^"]*?")|('[^']*?')|(`[^`]*?`)/, string: $ => /("[^"]*?")|('[^']*?')|(`[^`]*?`)/,
@ -192,6 +191,18 @@ module.exports = grammar({
')', ')',
)), )),
match: $ => seq(
'match',
$.expression,
'{',
repeat1(seq(
$.expression,
'=>',
$.item,
)),
'}',
),
while: $ => seq( while: $ => seq(
'while', 'while',
$.expression, $.expression,
@ -222,11 +233,12 @@ module.exports = grammar({
filter: $ => seq( filter: $ => seq(
'filter', 'filter',
$.identifier, field('count', optional($.expression)),
field('item_id', $.identifier),
'in', 'in',
$.expression, field('collection', $.expression),
'{', '{',
$.item, field('predicate', $.item),
'}', '}',
), ),

View File

@ -77,6 +77,10 @@
{ {
"type": "SYMBOL", "type": "SYMBOL",
"name": "remove" "name": "remove"
},
{
"type": "SYMBOL",
"name": "match"
} }
] ]
} }
@ -190,122 +194,200 @@
} }
] ]
}, },
"_numeric": {
"type": "TOKEN",
"content": {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "1"
},
{
"type": "STRING",
"value": "2"
},
{
"type": "STRING",
"value": "3"
},
{
"type": "STRING",
"value": "4"
},
{
"type": "STRING",
"value": "5"
},
{
"type": "STRING",
"value": "6"
},
{
"type": "STRING",
"value": "7"
},
{
"type": "STRING",
"value": "8"
},
{
"type": "STRING",
"value": "9"
},
{
"type": "STRING",
"value": "0"
}
]
}
}
},
"integer": { "integer": {
"type": "PREC_LEFT", "type": "PREC_LEFT",
"value": 0, "value": 0,
"content": { "content": {
"type": "SEQ", "type": "TOKEN",
"members": [ "content": {
{ "type": "SEQ",
"type": "CHOICE", "members": [
"members": [ {
{ "type": "CHOICE",
"type": "IMMEDIATE_TOKEN", "members": [
"content": { {
"type": "STRING", "type": "STRING",
"value": "-" "value": "-"
},
{
"type": "BLANK"
} }
}, ]
{ },
"type": "BLANK" {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "1"
},
{
"type": "STRING",
"value": "2"
},
{
"type": "STRING",
"value": "3"
},
{
"type": "STRING",
"value": "4"
},
{
"type": "STRING",
"value": "5"
},
{
"type": "STRING",
"value": "6"
},
{
"type": "STRING",
"value": "7"
},
{
"type": "STRING",
"value": "8"
},
{
"type": "STRING",
"value": "9"
},
{
"type": "STRING",
"value": "0"
}
]
} }
] }
}, ]
{ }
"type": "SYMBOL",
"name": "_numeric"
}
]
} }
}, },
"float": { "float": {
"type": "PREC_LEFT", "type": "PREC_LEFT",
"value": 0, "value": 0,
"content": { "content": {
"type": "SEQ", "type": "TOKEN",
"members": [ "content": {
{ "type": "SEQ",
"type": "CHOICE", "members": [
"members": [ {
{ "type": "CHOICE",
"type": "IMMEDIATE_TOKEN", "members": [
"content": { {
"type": "STRING", "type": "STRING",
"value": "-" "value": "-"
},
{
"type": "BLANK"
} }
}, ]
{ },
"type": "BLANK" {
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "1"
},
{
"type": "STRING",
"value": "2"
},
{
"type": "STRING",
"value": "3"
},
{
"type": "STRING",
"value": "4"
},
{
"type": "STRING",
"value": "5"
},
{
"type": "STRING",
"value": "6"
},
{
"type": "STRING",
"value": "7"
},
{
"type": "STRING",
"value": "8"
},
{
"type": "STRING",
"value": "9"
},
{
"type": "STRING",
"value": "0"
}
]
} }
] },
}, {
{
"type": "SYMBOL",
"name": "_numeric"
},
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "STRING", "type": "STRING",
"value": "." "value": "."
},
{
"type": "REPEAT1",
"content": {
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "1"
},
{
"type": "STRING",
"value": "2"
},
{
"type": "STRING",
"value": "3"
},
{
"type": "STRING",
"value": "4"
},
{
"type": "STRING",
"value": "5"
},
{
"type": "STRING",
"value": "6"
},
{
"type": "STRING",
"value": "7"
},
{
"type": "STRING",
"value": "8"
},
{
"type": "STRING",
"value": "9"
},
{
"type": "STRING",
"value": "0"
}
]
}
} }
}, ]
{ }
"type": "SYMBOL",
"name": "_numeric"
}
]
} }
}, },
"string": { "string": {
@ -852,6 +934,47 @@
] ]
} }
}, },
"match": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "match"
},
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "{"
},
{
"type": "REPEAT1",
"content": {
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "STRING",
"value": "=>"
},
{
"type": "SYMBOL",
"name": "item"
}
]
}
},
{
"type": "STRING",
"value": "}"
}
]
},
"while": { "while": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -951,24 +1074,52 @@
"value": "filter" "value": "filter"
}, },
{ {
"type": "SYMBOL", "type": "FIELD",
"name": "identifier" "name": "count",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "BLANK"
}
]
}
},
{
"type": "FIELD",
"name": "item_id",
"content": {
"type": "SYMBOL",
"name": "identifier"
}
}, },
{ {
"type": "STRING", "type": "STRING",
"value": "in" "value": "in"
}, },
{ {
"type": "SYMBOL", "type": "FIELD",
"name": "expression" "name": "collection",
"content": {
"type": "SYMBOL",
"name": "expression"
}
}, },
{ {
"type": "STRING", "type": "STRING",
"value": "{" "value": "{"
}, },
{ {
"type": "SYMBOL", "type": "FIELD",
"name": "item" "name": "predicate",
"content": {
"type": "SYMBOL",
"name": "item"
}
}, },
{ {
"type": "STRING", "type": "STRING",

View File

@ -128,24 +128,47 @@
{ {
"type": "filter", "type": "filter",
"named": true, "named": true,
"fields": {}, "fields": {
"children": { "collection": {
"multiple": true, "multiple": false,
"required": true, "required": true,
"types": [ "types": [
{ {
"type": "expression", "type": "expression",
"named": true "named": true
}, }
{ ]
"type": "identifier", },
"named": true "count": {
}, "multiple": false,
{ "required": false,
"type": "item", "types": [
"named": true {
} "type": "expression",
] "named": true
}
]
},
"item_id": {
"multiple": false,
"required": true,
"types": [
{
"type": "identifier",
"named": true
}
]
},
"predicate": {
"multiple": false,
"required": true,
"types": [
{
"type": "item",
"named": true
}
]
}
} }
}, },
{ {
@ -391,6 +414,25 @@
] ]
} }
}, },
{
"type": "match",
"named": true,
"fields": {},
"children": {
"multiple": true,
"required": true,
"types": [
{
"type": "expression",
"named": true
},
{
"type": "item",
"named": true
}
]
}
},
{ {
"type": "math", "type": "math",
"named": true, "named": true,
@ -520,6 +562,10 @@
"type": "insert", "type": "insert",
"named": true "named": true
}, },
{
"type": "match",
"named": true
},
{ {
"type": "remove", "type": "remove",
"named": true "named": true
@ -702,10 +748,6 @@
"type": "-=", "type": "-=",
"named": false "named": false
}, },
{
"type": ".",
"named": false
},
{ {
"type": "..", "type": "..",
"named": false "named": false
@ -734,6 +776,10 @@
"type": "==", "type": "==",
"named": false "named": false
}, },
{
"type": "=>",
"named": false
},
{ {
"type": ">", "type": ">",
"named": false "named": false
@ -846,6 +892,10 @@
"type": "length", "type": "length",
"named": false "named": false
}, },
{
"type": "match",
"named": false
},
{ {
"type": "metadata", "type": "metadata",
"named": false "named": false

File diff suppressed because it is too large Load Diff