Skip to content

Commit 6d6b863

Browse files
committed
Add a lowered representation for markers
1 parent 5eca3e9 commit 6d6b863

File tree

9 files changed

+320
-102
lines changed

9 files changed

+320
-102
lines changed

crates/uv-pep508/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ use url::Url;
2828

2929
use cursor::Cursor;
3030
pub use marker::{
31-
ContainsMarkerTree, ExtraMarkerTree, ExtraOperator, InMarkerTree, MarkerEnvironment,
31+
ContainsMarkerTree, ExtraMarkerTree, ExtraOperator, InMarkerTree, LoweredMarkerValueExtra,
32+
LoweredMarkerValueString, LoweredMarkerValueVersion, MarkerEnvironment,
3233
MarkerEnvironmentBuilder, MarkerExpression, MarkerOperator, MarkerTree, MarkerTreeContents,
3334
MarkerTreeKind, MarkerValue, MarkerValueExtra, MarkerValueString, MarkerValueVersion,
3435
MarkerWarningKind, StringMarkerTree, StringVersion, VersionMarkerTree,

crates/uv-pep508/src/marker/algebra.rs

+66-24
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,12 @@ use std::sync::LazyLock;
5656
use uv_pep440::{release_specifier_to_range, Operator, Version, VersionSpecifier};
5757
use version_ranges::Ranges;
5858

59+
use crate::marker::lowering::{
60+
LoweredMarkerValueExtra, LoweredMarkerValueString, LoweredMarkerValueVersion,
61+
};
5962
use crate::marker::MarkerValueExtra;
6063
use crate::ExtraOperator;
61-
use crate::{MarkerExpression, MarkerOperator, MarkerValueString, MarkerValueVersion};
64+
use crate::{MarkerExpression, MarkerOperator, MarkerValueVersion};
6265

6366
/// The global node interner.
6467
pub(crate) static INTERNER: LazyLock<Interner> = LazyLock::new(Interner::default);
@@ -161,7 +164,7 @@ impl InternerGuard<'_> {
161164
specifier,
162165
} => match python_version_to_full_version(normalize_specifier(specifier)) {
163166
Ok(specifier) => (
164-
Variable::Version(MarkerValueVersion::PythonFullVersion),
167+
Variable::Version(LoweredMarkerValueVersion::PythonFullVersion),
165168
Edges::from_specifier(specifier),
166169
),
167170
Err(node) => return node,
@@ -172,24 +175,25 @@ impl InternerGuard<'_> {
172175
negated,
173176
} => match Edges::from_python_versions(versions, negated) {
174177
Ok(edges) => (
175-
Variable::Version(MarkerValueVersion::PythonFullVersion),
178+
Variable::Version(LoweredMarkerValueVersion::PythonFullVersion),
176179
edges,
177180
),
178181
Err(node) => return node,
179182
},
180183
// A variable representing the output of a version key. Edges correspond
181184
// to disjoint version ranges.
182-
MarkerExpression::Version { key, specifier } => {
183-
(Variable::Version(key), Edges::from_specifier(specifier))
184-
}
185+
MarkerExpression::Version { key, specifier } => (
186+
Variable::Version(key.into()),
187+
Edges::from_specifier(specifier),
188+
),
185189
// A variable representing the output of a version key. Edges correspond
186190
// to disjoint version ranges.
187191
MarkerExpression::VersionIn {
188192
key,
189193
versions,
190194
negated,
191195
} => (
192-
Variable::Version(key),
196+
Variable::Version(key.into()),
193197
Edges::from_versions(&versions, negated),
194198
),
195199
// The `in` and `contains` operators are a bit different than other operators.
@@ -206,38 +210,76 @@ impl InternerGuard<'_> {
206210
key,
207211
operator: MarkerOperator::In,
208212
value,
209-
} => (Variable::In { key, value }, Edges::from_bool(true)),
213+
} => (
214+
Variable::In {
215+
key: key.into(),
216+
value,
217+
},
218+
Edges::from_bool(true),
219+
),
210220
MarkerExpression::String {
211221
key,
212222
operator: MarkerOperator::NotIn,
213223
value,
214-
} => (Variable::In { key, value }, Edges::from_bool(false)),
224+
} => (
225+
Variable::In {
226+
key: key.into(),
227+
value,
228+
},
229+
Edges::from_bool(false),
230+
),
215231
MarkerExpression::String {
216232
key,
217233
operator: MarkerOperator::Contains,
218234
value,
219-
} => (Variable::Contains { key, value }, Edges::from_bool(true)),
235+
} => (
236+
Variable::Contains {
237+
key: key.into(),
238+
value,
239+
},
240+
Edges::from_bool(true),
241+
),
220242
MarkerExpression::String {
221243
key,
222244
operator: MarkerOperator::NotContains,
223245
value,
224-
} => (Variable::Contains { key, value }, Edges::from_bool(false)),
246+
} => (
247+
Variable::Contains {
248+
key: key.into(),
249+
value,
250+
},
251+
Edges::from_bool(false),
252+
),
225253
// A variable representing the output of a string key. Edges correspond
226254
// to disjoint string ranges.
227255
MarkerExpression::String {
228256
key,
229257
operator,
230258
value,
231-
} => (Variable::String(key), Edges::from_string(operator, value)),
259+
} => (
260+
Variable::String(key.into()),
261+
Edges::from_string(operator, value),
262+
),
232263
// A variable representing the existence or absence of a particular extra.
233264
MarkerExpression::Extra {
234-
name,
265+
name: MarkerValueExtra::Extra(extra),
235266
operator: ExtraOperator::Equal,
236-
} => (Variable::Extra(name), Edges::from_bool(true)),
267+
} => (
268+
Variable::Extra(LoweredMarkerValueExtra::Extra(extra)),
269+
Edges::from_bool(true),
270+
),
237271
MarkerExpression::Extra {
238-
name,
272+
name: MarkerValueExtra::Extra(extra),
239273
operator: ExtraOperator::NotEqual,
240-
} => (Variable::Extra(name), Edges::from_bool(false)),
274+
} => (
275+
Variable::Extra(LoweredMarkerValueExtra::Extra(extra)),
276+
Edges::from_bool(false),
277+
),
278+
// Invalid extras are always `false`.
279+
MarkerExpression::Extra {
280+
name: MarkerValueExtra::Arbitrary(_),
281+
..
282+
} => return NodeId::FALSE,
241283
};
242284

243285
self.create_node(var, children)
@@ -391,7 +433,7 @@ impl InternerGuard<'_> {
391433
// Look for a `python_full_version` expression, otherwise
392434
// we recursively simplify.
393435
let Node {
394-
var: Variable::Version(MarkerValueVersion::PythonFullVersion),
436+
var: Variable::Version(LoweredMarkerValueVersion::PythonFullVersion),
395437
children: Edges::Version { ref edges },
396438
} = node
397439
else {
@@ -464,7 +506,7 @@ impl InternerGuard<'_> {
464506
return NodeId::FALSE;
465507
}
466508
if matches!(i, NodeId::TRUE) {
467-
let var = Variable::Version(MarkerValueVersion::PythonFullVersion);
509+
let var = Variable::Version(LoweredMarkerValueVersion::PythonFullVersion);
468510
let edges = Edges::Version {
469511
edges: Edges::from_range(&py_range),
470512
};
@@ -473,7 +515,7 @@ impl InternerGuard<'_> {
473515

474516
let node = self.shared.node(i);
475517
let Node {
476-
var: Variable::Version(MarkerValueVersion::PythonFullVersion),
518+
var: Variable::Version(LoweredMarkerValueVersion::PythonFullVersion),
477519
children: Edges::Version { ref edges },
478520
} = node
479521
else {
@@ -569,26 +611,26 @@ pub(crate) enum Variable {
569611
///
570612
/// This is the highest order variable as it typically contains the most complex
571613
/// ranges, allowing us to merge ranges at the top-level.
572-
Version(MarkerValueVersion),
614+
Version(LoweredMarkerValueVersion),
573615
/// A string marker, such as `os_name`.
574-
String(MarkerValueString),
616+
String(LoweredMarkerValueString),
575617
/// A variable representing a `<key> in <value>` expression for a particular
576618
/// string marker and value.
577619
In {
578-
key: MarkerValueString,
620+
key: LoweredMarkerValueString,
579621
value: String,
580622
},
581623
/// A variable representing a `<value> in <key>` expression for a particular
582624
/// string marker and value.
583625
Contains {
584-
key: MarkerValueString,
626+
key: LoweredMarkerValueString,
585627
value: String,
586628
},
587629
/// A variable representing the existence or absence of a given extra.
588630
///
589631
/// We keep extras at the leaves of the tree, so when simplifying extras we can
590632
/// trivially remove the leaves without having to reconstruct the entire tree.
591-
Extra(MarkerValueExtra),
633+
Extra(LoweredMarkerValueExtra),
592634
}
593635

594636
/// A decision node in an Algebraic Decision Diagram.

crates/uv-pep508/src/marker/environment.rs

+22-21
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::sync::Arc;
22

33
use uv_pep440::{Version, VersionParseError};
44

5-
use crate::{MarkerValueString, MarkerValueVersion, StringVersion};
5+
use crate::{LoweredMarkerValueString, LoweredMarkerValueVersion, StringVersion};
66

77
/// The marker values for a python interpreter, normally the current one
88
///
@@ -33,35 +33,36 @@ struct MarkerEnvironmentInner {
3333

3434
impl MarkerEnvironment {
3535
/// Returns of the PEP 440 version typed value of the key in the current environment
36-
pub fn get_version(&self, key: MarkerValueVersion) -> &Version {
36+
pub fn get_version(&self, key: LoweredMarkerValueVersion) -> &Version {
3737
match key {
38-
MarkerValueVersion::ImplementationVersion => &self.implementation_version().version,
39-
MarkerValueVersion::PythonFullVersion => &self.python_full_version().version,
40-
MarkerValueVersion::PythonVersion => &self.python_version().version,
38+
LoweredMarkerValueVersion::ImplementationVersion => {
39+
&self.implementation_version().version
40+
}
41+
LoweredMarkerValueVersion::PythonFullVersion => &self.python_full_version().version,
42+
LoweredMarkerValueVersion::PythonVersion => &self.python_version().version,
4143
}
4244
}
4345

4446
/// Returns of the stringly typed value of the key in the current environment
45-
pub fn get_string(&self, key: MarkerValueString) -> &str {
47+
pub fn get_string(&self, key: LoweredMarkerValueString) -> &str {
4648
match key {
47-
MarkerValueString::ImplementationName => self.implementation_name(),
48-
MarkerValueString::OsName | MarkerValueString::OsNameDeprecated => self.os_name(),
49-
MarkerValueString::PlatformMachine | MarkerValueString::PlatformMachineDeprecated => {
50-
self.platform_machine()
49+
LoweredMarkerValueString::ImplementationName => self.implementation_name(),
50+
LoweredMarkerValueString::OsName | LoweredMarkerValueString::OsNameDeprecated => {
51+
self.os_name()
5152
}
52-
MarkerValueString::PlatformPythonImplementation
53-
| MarkerValueString::PlatformPythonImplementationDeprecated
54-
| MarkerValueString::PythonImplementationDeprecated => {
53+
LoweredMarkerValueString::PlatformMachine
54+
| LoweredMarkerValueString::PlatformMachineDeprecated => self.platform_machine(),
55+
LoweredMarkerValueString::PlatformPythonImplementation
56+
| LoweredMarkerValueString::PlatformPythonImplementationDeprecated
57+
| LoweredMarkerValueString::PythonImplementationDeprecated => {
5558
self.platform_python_implementation()
5659
}
57-
MarkerValueString::PlatformRelease => self.platform_release(),
58-
MarkerValueString::PlatformSystem => self.platform_system(),
59-
MarkerValueString::PlatformVersion | MarkerValueString::PlatformVersionDeprecated => {
60-
self.platform_version()
61-
}
62-
MarkerValueString::SysPlatform | MarkerValueString::SysPlatformDeprecated => {
63-
self.sys_platform()
64-
}
60+
LoweredMarkerValueString::PlatformRelease => self.platform_release(),
61+
LoweredMarkerValueString::PlatformSystem => self.platform_system(),
62+
LoweredMarkerValueString::PlatformVersion
63+
| LoweredMarkerValueString::PlatformVersionDeprecated => self.platform_version(),
64+
LoweredMarkerValueString::SysPlatform
65+
| LoweredMarkerValueString::SysPlatformDeprecated => self.sys_platform(),
6566
}
6667
}
6768
}

0 commit comments

Comments
 (0)