Skip to content

Commit 0568794

Browse files
stepanchegfacebook-github-bot
authored andcommitted
special case for type(x) == "y"
Summary: Simpler version of D30849928: handle `type(x) == "y"` as a single instruction in the interpreter. Reviewed By: ndmitchell Differential Revision: D30867542 fbshipit-source-id: f014d87e6c8a73f70886ada320af6e99e5a7660d
1 parent be123bb commit 0568794

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

starlark/src/eval/fragment/expr.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use crate::{
3434
dict::Dict,
3535
function::{BoundMethod, NativeAttribute},
3636
list::List,
37+
string::StarlarkStr,
3738
tuple::{FrozenTuple, Tuple},
3839
AttrType, FrozenHeap, FrozenValue, Heap, Value, ValueError, ValueLike,
3940
},
@@ -96,6 +97,29 @@ fn eval_compare(
9697
})
9798
}
9899

100+
/// Try fold expression `cmp(l == r)` into `cmp(type(x) == "y")`.
101+
/// Return original `l` and `r` arguments if fold was unsuccessful.
102+
fn try_eval_type_is(
103+
l: ExprCompiledValue,
104+
r: ExprCompiledValue,
105+
cmp: fn(bool) -> bool,
106+
) -> Result<ExprCompiledValue, (ExprCompiledValue, ExprCompiledValue)> {
107+
match (l, r) {
108+
(ExprCompiledValue::Type(l), ExprCompiledValue::Value(r)) => {
109+
if let Some(r) = r.downcast_frozen_ref::<StarlarkStr>() {
110+
let l = ExprCompiledValue::Compiled(l);
111+
let t = r.map(|r| r.unpack());
112+
Ok(expr!("type_is", l, |_eval| {
113+
Value::new_bool(cmp(l.get_type() == t.as_ref()))
114+
}))
115+
} else {
116+
Err((ExprCompiledValue::Type(l), ExprCompiledValue::Value(r)))
117+
}
118+
}
119+
(l, r) => Err((l, r)),
120+
}
121+
}
122+
99123
fn eval_equals(
100124
span: Span,
101125
l: ExprCompiledValue,
@@ -109,6 +133,16 @@ fn eval_equals(
109133
}
110134
}
111135

136+
let (l, r) = match try_eval_type_is(l, r, cmp) {
137+
Ok(e) => return e,
138+
Err((l, r)) => (l, r),
139+
};
140+
141+
let (r, l) = match try_eval_type_is(r, l, cmp) {
142+
Ok(e) => return e,
143+
Err((r, l)) => (r, l),
144+
};
145+
112146
expr!("equals", l, r, |eval| {
113147
Value::new_bool(cmp(expr_throw(l.equals(r), span, eval)?))
114148
})

0 commit comments

Comments
 (0)