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(),
};
async {};
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;
}
}
values.par_iter().try_for_each(|value| {
let mut context = Map::new(); let mut context = Map::new();
context.variables_mut().insert(key.clone(), value.clone()); context.variables_mut().insert(key.clone(), value.clone());
let should_include = self.item.run(source, &mut context)?.as_boolean()?; 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 { if should_include {
new_values.items_mut().push(value.clone()); new_values.items_mut().push(value);
}
});
} }
Ok::<(), Error>(())
})?;
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(
optional('-'),
repeat1(
choice('1', '2', '3', '4', '5', '6', '7', '8', '9', '0') 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,9 +194,27 @@
} }
] ]
}, },
"_numeric": { "integer": {
"type": "PREC_LEFT",
"value": 0,
"content": {
"type": "TOKEN", "type": "TOKEN",
"content": { "content": {
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": "-"
},
{
"type": "BLANK"
}
]
},
{
"type": "REPEAT1", "type": "REPEAT1",
"content": { "content": {
"type": "CHOICE", "type": "CHOICE",
@ -240,38 +262,15 @@
] ]
} }
} }
},
"integer": {
"type": "PREC_LEFT",
"value": 0,
"content": {
"type": "SEQ",
"members": [
{
"type": "CHOICE",
"members": [
{
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "STRING",
"value": "-"
}
},
{
"type": "BLANK"
}
] ]
},
{
"type": "SYMBOL",
"name": "_numeric"
} }
]
} }
}, },
"float": { "float": {
"type": "PREC_LEFT", "type": "PREC_LEFT",
"value": 0, "value": 0,
"content": {
"type": "TOKEN",
"content": { "content": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -279,11 +278,8 @@
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
{ {
"type": "IMMEDIATE_TOKEN",
"content": {
"type": "STRING", "type": "STRING",
"value": "-" "value": "-"
}
}, },
{ {
"type": "BLANK" "type": "BLANK"
@ -291,23 +287,109 @@
] ]
}, },
{ {
"type": "SYMBOL", "type": "REPEAT1",
"name": "_numeric"
},
{
"type": "IMMEDIATE_TOKEN",
"content": { "content": {
"type": "CHOICE",
"members": [
{
"type": "STRING", "type": "STRING",
"value": "." "value": "1"
}
}, },
{ {
"type": "SYMBOL", "type": "STRING",
"name": "_numeric" "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": "STRING",
"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"
}
]
}
}
]
}
}
},
"string": { "string": {
"type": "PATTERN", "type": "PATTERN",
"value": "(\"[^\"]*?\")|('[^']*?')|(`[^`]*?`)" "value": "(\"[^\"]*?\")|('[^']*?')|(`[^`]*?`)"
@ -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": "FIELD",
"name": "count",
"content": {
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "expression"
},
{
"type": "BLANK"
}
]
}
},
{
"type": "FIELD",
"name": "item_id",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "identifier" "name": "identifier"
}
}, },
{ {
"type": "STRING", "type": "STRING",
"value": "in" "value": "in"
}, },
{ {
"type": "FIELD",
"name": "collection",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "expression" "name": "expression"
}
}, },
{ {
"type": "STRING", "type": "STRING",
"value": "{" "value": "{"
}, },
{ {
"type": "FIELD",
"name": "predicate",
"content": {
"type": "SYMBOL", "type": "SYMBOL",
"name": "item" "name": "item"
}
}, },
{ {
"type": "STRING", "type": "STRING",

View File

@ -128,25 +128,48 @@
{ {
"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
}
]
}, },
"count": {
"multiple": false,
"required": false,
"types": [
{
"type": "expression",
"named": true
}
]
},
"item_id": {
"multiple": false,
"required": true,
"types": [
{ {
"type": "identifier", "type": "identifier",
"named": true "named": true
}
]
}, },
"predicate": {
"multiple": false,
"required": true,
"types": [
{ {
"type": "item", "type": "item",
"named": true "named": true
} }
] ]
} }
}
}, },
{ {
"type": "find", "type": "find",
@ -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