snail-lang 0.3.6__tar.gz → 0.3.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {snail_lang-0.3.6 → snail_lang-0.3.7}/Cargo.lock +7 -7
- {snail_lang-0.3.6 → snail_lang-0.3.7}/PKG-INFO +18 -10
- {snail_lang-0.3.6 → snail_lang-0.3.7}/README.md +17 -9
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-ast/Cargo.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-ast/src/ast.rs +3 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-core/Cargo.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-error/Cargo.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-error/src/lib.rs +15 -7
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/Cargo.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/constants.rs +2 -3
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/expr.rs +517 -49
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/Cargo.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/expr.rs +6 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/lib.rs +1 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/snail.pest +4 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/string.rs +1 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/util.rs +1 -0
- snail_lang-0.3.7/crates/snail-parser/tests/common.rs +84 -0
- snail_lang-0.3.7/crates/snail-parser/tests/errors.rs +195 -0
- snail_lang-0.3.7/crates/snail-parser/tests/parser.rs +634 -0
- snail_lang-0.3.7/crates/snail-parser/tests/statements.rs +409 -0
- snail_lang-0.3.7/crates/snail-parser/tests/syntax_expressions.rs +369 -0
- snail_lang-0.3.7/crates/snail-parser/tests/syntax_strings.rs +92 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-python/Cargo.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-python/src/lib.rs +16 -10
- {snail_lang-0.3.6 → snail_lang-0.3.7}/pyproject.toml +1 -1
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/cli.py +2 -0
- snail_lang-0.3.7/python/snail/runtime/__init__.py +59 -0
- snail_lang-0.3.7/python/snail/runtime/structured_accessor.py +75 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/runtime/subprocess.py +2 -2
- snail_lang-0.3.6/crates/snail-parser/tests/parser.rs +0 -837
- snail_lang-0.3.6/python/snail/runtime/__init__.py +0 -27
- snail_lang-0.3.6/python/snail/runtime/structured_accessor.py +0 -115
- {snail_lang-0.3.6 → snail_lang-0.3.7}/Cargo.toml +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/LICENSE +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-ast/README.md +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-ast/src/awk.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-ast/src/lib.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-core/README.md +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-core/src/lib.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-error/README.md +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/README.md +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/awk.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/helpers.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/lib.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/operators.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/program.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/py_ast.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-lower/src/stmt.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/README.md +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/awk.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/literal.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/crates/snail-parser/src/stmt.rs +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/__init__.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/runtime/compact_try.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/runtime/regex.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/__init__.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/LICENSE +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/__init__.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/ast.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/compat.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/exceptions.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/functions.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/lexer.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/parser.py +0 -0
- {snail_lang-0.3.6 → snail_lang-0.3.7}/python/snail/vendor/jmespath/visitor.py +0 -0
|
@@ -485,11 +485,11 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|
|
485
485
|
|
|
486
486
|
[[package]]
|
|
487
487
|
name = "snail-ast"
|
|
488
|
-
version = "0.3.
|
|
488
|
+
version = "0.3.7"
|
|
489
489
|
|
|
490
490
|
[[package]]
|
|
491
491
|
name = "snail-core"
|
|
492
|
-
version = "0.3.
|
|
492
|
+
version = "0.3.7"
|
|
493
493
|
dependencies = [
|
|
494
494
|
"pyo3",
|
|
495
495
|
"snail-ast",
|
|
@@ -500,14 +500,14 @@ dependencies = [
|
|
|
500
500
|
|
|
501
501
|
[[package]]
|
|
502
502
|
name = "snail-error"
|
|
503
|
-
version = "0.3.
|
|
503
|
+
version = "0.3.7"
|
|
504
504
|
dependencies = [
|
|
505
505
|
"snail-ast",
|
|
506
506
|
]
|
|
507
507
|
|
|
508
508
|
[[package]]
|
|
509
509
|
name = "snail-lower"
|
|
510
|
-
version = "0.3.
|
|
510
|
+
version = "0.3.7"
|
|
511
511
|
dependencies = [
|
|
512
512
|
"pyo3",
|
|
513
513
|
"snail-ast",
|
|
@@ -516,7 +516,7 @@ dependencies = [
|
|
|
516
516
|
|
|
517
517
|
[[package]]
|
|
518
518
|
name = "snail-parser"
|
|
519
|
-
version = "0.3.
|
|
519
|
+
version = "0.3.7"
|
|
520
520
|
dependencies = [
|
|
521
521
|
"pest",
|
|
522
522
|
"pest_derive",
|
|
@@ -526,7 +526,7 @@ dependencies = [
|
|
|
526
526
|
|
|
527
527
|
[[package]]
|
|
528
528
|
name = "snail-proptest"
|
|
529
|
-
version = "0.3.
|
|
529
|
+
version = "0.3.7"
|
|
530
530
|
dependencies = [
|
|
531
531
|
"proptest",
|
|
532
532
|
"pyo3",
|
|
@@ -540,7 +540,7 @@ dependencies = [
|
|
|
540
540
|
|
|
541
541
|
[[package]]
|
|
542
542
|
name = "snail-python"
|
|
543
|
-
version = "0.3.
|
|
543
|
+
version = "0.3.7"
|
|
544
544
|
dependencies = [
|
|
545
545
|
"pyo3",
|
|
546
546
|
"snail-core",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snail-lang
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.7
|
|
4
4
|
Requires-Dist: maturin>=1.5 ; extra == 'dev'
|
|
5
5
|
Requires-Dist: pytest ; extra == 'dev'
|
|
6
6
|
Provides-Extra: dev
|
|
@@ -64,7 +64,7 @@ The `?` operator makes error handling terse yet expressive:
|
|
|
64
64
|
err = risky_operation()?
|
|
65
65
|
|
|
66
66
|
# Provide a fallback value (exception available as $e)
|
|
67
|
-
value =
|
|
67
|
+
value = js(data):{}?
|
|
68
68
|
details = fetch_url(url):"Error: {$e}"?
|
|
69
69
|
|
|
70
70
|
# Access attributes directly
|
|
@@ -101,7 +101,7 @@ Built-in variables: `$l` (line), `$f` (fields), `$n` (line number), `$fn` (per-f
|
|
|
101
101
|
|
|
102
102
|
### Pipeline Operator
|
|
103
103
|
|
|
104
|
-
The `|` operator enables data pipelining through
|
|
104
|
+
The `|` operator enables data pipelining through pipeline-aware callables:
|
|
105
105
|
|
|
106
106
|
```snail
|
|
107
107
|
# Pipe data to subprocess stdin
|
|
@@ -112,29 +112,37 @@ output = "foo\nbar" | $(grep foo) | $(wc -l)
|
|
|
112
112
|
|
|
113
113
|
# Custom pipeline handlers
|
|
114
114
|
class Doubler {
|
|
115
|
-
def
|
|
115
|
+
def __call__(self, x) { return x * 2 }
|
|
116
116
|
}
|
|
117
117
|
doubled = 21 | Doubler() # yields 42
|
|
118
118
|
|
|
119
|
-
#
|
|
120
|
-
|
|
119
|
+
# Use placeholders to control where piped values land in calls
|
|
120
|
+
greeting = "World" | greet("Hello ", _) # greet("Hello ", "World")
|
|
121
|
+
excited = "World" | greet(_, "!") # greet("World", "!")
|
|
122
|
+
formal = "World" | greet("Hello ", suffix=_) # greet("Hello ", "World")
|
|
121
123
|
```
|
|
122
124
|
|
|
125
|
+
When a pipeline targets a call expression, the left-hand value is passed to the
|
|
126
|
+
resulting callable. If the call includes a single `_` placeholder, Snail substitutes
|
|
127
|
+
the piped value at that position (including keyword arguments). Only one
|
|
128
|
+
placeholder is allowed in a piped call. Outside of pipeline calls, `_` remains a
|
|
129
|
+
normal identifier.
|
|
130
|
+
|
|
123
131
|
### JSON Queries with JMESPath
|
|
124
132
|
|
|
125
|
-
Parse and query JSON data with the `
|
|
133
|
+
Parse and query JSON data with the `js()` function and structured pipeline accessor:
|
|
126
134
|
|
|
127
135
|
```snail
|
|
128
136
|
# Parse JSON and query with $[jmespath]
|
|
129
|
-
data =
|
|
137
|
+
data = js($(curl -s api.example.com/users))
|
|
130
138
|
names = data | $[users[*].name]
|
|
131
139
|
first_email = data | $[users[0].email]
|
|
132
140
|
|
|
133
141
|
# Inline parsing and querying
|
|
134
|
-
result =
|
|
142
|
+
result = js('{"foo": 12}') | $[foo]
|
|
135
143
|
|
|
136
144
|
# JSONL parsing returns a list
|
|
137
|
-
names =
|
|
145
|
+
names = js('{"name": "Ada"}\n{"name": "Lin"}') | $[[*].name]
|
|
138
146
|
```
|
|
139
147
|
|
|
140
148
|
### Full Python Interoperability
|
|
@@ -53,7 +53,7 @@ The `?` operator makes error handling terse yet expressive:
|
|
|
53
53
|
err = risky_operation()?
|
|
54
54
|
|
|
55
55
|
# Provide a fallback value (exception available as $e)
|
|
56
|
-
value =
|
|
56
|
+
value = js(data):{}?
|
|
57
57
|
details = fetch_url(url):"Error: {$e}"?
|
|
58
58
|
|
|
59
59
|
# Access attributes directly
|
|
@@ -90,7 +90,7 @@ Built-in variables: `$l` (line), `$f` (fields), `$n` (line number), `$fn` (per-f
|
|
|
90
90
|
|
|
91
91
|
### Pipeline Operator
|
|
92
92
|
|
|
93
|
-
The `|` operator enables data pipelining through
|
|
93
|
+
The `|` operator enables data pipelining through pipeline-aware callables:
|
|
94
94
|
|
|
95
95
|
```snail
|
|
96
96
|
# Pipe data to subprocess stdin
|
|
@@ -101,29 +101,37 @@ output = "foo\nbar" | $(grep foo) | $(wc -l)
|
|
|
101
101
|
|
|
102
102
|
# Custom pipeline handlers
|
|
103
103
|
class Doubler {
|
|
104
|
-
def
|
|
104
|
+
def __call__(self, x) { return x * 2 }
|
|
105
105
|
}
|
|
106
106
|
doubled = 21 | Doubler() # yields 42
|
|
107
107
|
|
|
108
|
-
#
|
|
109
|
-
|
|
108
|
+
# Use placeholders to control where piped values land in calls
|
|
109
|
+
greeting = "World" | greet("Hello ", _) # greet("Hello ", "World")
|
|
110
|
+
excited = "World" | greet(_, "!") # greet("World", "!")
|
|
111
|
+
formal = "World" | greet("Hello ", suffix=_) # greet("Hello ", "World")
|
|
110
112
|
```
|
|
111
113
|
|
|
114
|
+
When a pipeline targets a call expression, the left-hand value is passed to the
|
|
115
|
+
resulting callable. If the call includes a single `_` placeholder, Snail substitutes
|
|
116
|
+
the piped value at that position (including keyword arguments). Only one
|
|
117
|
+
placeholder is allowed in a piped call. Outside of pipeline calls, `_` remains a
|
|
118
|
+
normal identifier.
|
|
119
|
+
|
|
112
120
|
### JSON Queries with JMESPath
|
|
113
121
|
|
|
114
|
-
Parse and query JSON data with the `
|
|
122
|
+
Parse and query JSON data with the `js()` function and structured pipeline accessor:
|
|
115
123
|
|
|
116
124
|
```snail
|
|
117
125
|
# Parse JSON and query with $[jmespath]
|
|
118
|
-
data =
|
|
126
|
+
data = js($(curl -s api.example.com/users))
|
|
119
127
|
names = data | $[users[*].name]
|
|
120
128
|
first_email = data | $[users[0].email]
|
|
121
129
|
|
|
122
130
|
# Inline parsing and querying
|
|
123
|
-
result =
|
|
131
|
+
result = js('{"foo": 12}') | $[foo]
|
|
124
132
|
|
|
125
133
|
# JSONL parsing returns a list
|
|
126
|
-
names =
|
|
134
|
+
names = js('{"name": "Ada"}\n{"name": "Lin"}') | $[[*].name]
|
|
127
135
|
```
|
|
128
136
|
|
|
129
137
|
### Full Python Interoperability
|
|
@@ -42,21 +42,29 @@ impl fmt::Display for ParseError {
|
|
|
42
42
|
impl Error for ParseError {}
|
|
43
43
|
|
|
44
44
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
45
|
-
pub
|
|
46
|
-
|
|
45
|
+
pub enum LowerError {
|
|
46
|
+
Message(String),
|
|
47
|
+
MultiplePlaceholders { span: SourceSpan },
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
impl LowerError {
|
|
50
51
|
pub fn new(message: impl Into<String>) -> Self {
|
|
51
|
-
Self
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
Self::Message(message.into())
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pub fn multiple_placeholders(span: SourceSpan) -> Self {
|
|
56
|
+
Self::MultiplePlaceholders { span }
|
|
54
57
|
}
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
impl fmt::Display for LowerError {
|
|
58
61
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
59
|
-
|
|
62
|
+
match self {
|
|
63
|
+
LowerError::Message(message) => write!(f, "{message}"),
|
|
64
|
+
LowerError::MultiplePlaceholders { .. } => {
|
|
65
|
+
write!(f, "pipeline calls may include at most one placeholder")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
60
68
|
}
|
|
61
69
|
}
|
|
62
70
|
|
|
@@ -101,7 +109,7 @@ impl From<LowerError> for SnailError {
|
|
|
101
109
|
pub fn format_snail_error(err: &SnailError, filename: &str) -> String {
|
|
102
110
|
match err {
|
|
103
111
|
SnailError::Parse(parse) => format_parse_error(parse, filename),
|
|
104
|
-
SnailError::Lower(lower) => format!("error: {}"
|
|
112
|
+
SnailError::Lower(lower) => format!("error: {lower}"),
|
|
105
113
|
}
|
|
106
114
|
}
|
|
107
115
|
|
|
@@ -5,9 +5,8 @@ pub const SNAIL_SUBPROCESS_CAPTURE_CLASS: &str = "__SnailSubprocessCapture";
|
|
|
5
5
|
pub const SNAIL_SUBPROCESS_STATUS_CLASS: &str = "__SnailSubprocessStatus";
|
|
6
6
|
pub const SNAIL_REGEX_SEARCH: &str = "__snail_regex_search";
|
|
7
7
|
pub const SNAIL_REGEX_COMPILE: &str = "__snail_regex_compile";
|
|
8
|
-
pub const
|
|
9
|
-
pub const
|
|
10
|
-
pub const SNAIL_JSON_PIPELINE_WRAPPER_CLASS: &str = "__SnailJsonPipelineWrapper";
|
|
8
|
+
pub const SNAIL_JMESPATH_QUERY: &str = "__snail_jmespath_query";
|
|
9
|
+
pub const SNAIL_PARTIAL_HELPER: &str = "__snail_partial";
|
|
11
10
|
|
|
12
11
|
// Awk-related constants (public within crate)
|
|
13
12
|
pub(crate) const SNAIL_AWK_LINE: &str = "$l";
|