Skip to content

Commit 89bc023

Browse files
milianwogoffart
authored andcommitted
Optimize: Filter/map rowan nodes instead of doing multiple lookups
Instead of doing potentially multiple calls in the chained calls, each of which would allocate in rowan, we now only call the iterator function once and then leverage `find_map`. This is arguably even more readable and it removes ~300k allocations and speeds up parsing. Before: ``` Time (mean ± σ): 930.7 ms ± 15.1 ms [User: 678.7 ms, System: 165.5 ms] Range (min … max): 906.4 ms … 956.3 ms 10 runs allocations: 2339130 ``` After: ``` Time (mean ± σ): 914.6 ms ± 22.7 ms [User: 649.6 ms, System: 174.5 ms] Range (min … max): 874.8 ms … 946.3 ms 10 runs allocations: 2017915 ```
1 parent 79e1592 commit 89bc023

File tree

1 file changed

+125
-96
lines changed

1 file changed

+125
-96
lines changed

internal/compiler/passes/resolving.rs

Lines changed: 125 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,11 @@ impl Expression {
138138
pub fn from_binding_expression_node(node: SyntaxNode, ctx: &mut LookupCtx) -> Self {
139139
debug_assert_eq!(node.kind(), SyntaxKind::BindingExpression);
140140
let e = node
141-
.child_node(SyntaxKind::Expression)
142-
.map(|n| Self::from_expression_node(n.into(), ctx))
143-
.or_else(|| {
144-
node.child_node(SyntaxKind::CodeBlock)
145-
.map(|c| Self::from_codeblock_node(c.into(), ctx))
141+
.children()
142+
.find_map(|n| match n.kind() {
143+
SyntaxKind::Expression => Some(Self::from_expression_node(n.into(), ctx)),
144+
SyntaxKind::CodeBlock => Some(Self::from_codeblock_node(n.into(), ctx)),
145+
_ => None,
146146
})
147147
.unwrap_or(Self::Invalid);
148148
if ctx.property_type == Type::LogicalLength && e.ty() == Type::Percent {
@@ -255,76 +255,93 @@ impl Expression {
255255
}
256256

257257
fn from_expression_node(node: syntax_nodes::Expression, ctx: &mut LookupCtx) -> Self {
258-
node.Expression()
259-
.map(|n| Self::from_expression_node(n, ctx))
260-
.or_else(|| node.AtImageUrl().map(|n| Self::from_at_image_url_node(n, ctx)))
261-
.or_else(|| node.AtGradient().map(|n| Self::from_at_gradient(n, ctx)))
262-
.or_else(|| node.AtTr().map(|n| Self::from_at_tr(n, ctx)))
263-
.or_else(|| {
264-
node.QualifiedName().map(|n| {
265-
let exp =
266-
Self::from_qualified_name_node(n.clone(), ctx, LookupPhase::default());
267-
if matches!(exp.ty(), Type::Function { .. } | Type::Callback { .. }) {
268-
ctx.diag.push_error(
269-
format!(
270-
"'{}' must be called. Did you forgot the '()'?",
271-
QualifiedTypeName::from_node(n.clone())
272-
),
273-
&n,
274-
)
258+
node.children_with_tokens()
259+
.find_map(|child| match child {
260+
NodeOrToken::Node(node) => match node.kind() {
261+
SyntaxKind::Expression => Some(Self::from_expression_node(node.into(), ctx)),
262+
SyntaxKind::AtImageUrl => Some(Self::from_at_image_url_node(node.into(), ctx)),
263+
SyntaxKind::AtGradient => Some(Self::from_at_gradient(node.into(), ctx)),
264+
SyntaxKind::AtTr => Some(Self::from_at_tr(node.into(), ctx)),
265+
SyntaxKind::QualifiedName => {
266+
let exp = Self::from_qualified_name_node(
267+
node.clone().into(),
268+
ctx,
269+
LookupPhase::default(),
270+
);
271+
if matches!(exp.ty(), Type::Function { .. } | Type::Callback { .. }) {
272+
ctx.diag.push_error(
273+
format!(
274+
"'{}' must be called. Did you forgot the '()'?",
275+
QualifiedTypeName::from_node(node.clone().into())
276+
),
277+
&node,
278+
)
279+
}
280+
Some(exp)
275281
}
276-
exp
277-
})
278-
})
279-
.or_else(|| {
280-
node.child_text(SyntaxKind::StringLiteral).map(|s| {
281-
crate::literals::unescape_string(&s).map(Self::StringLiteral).unwrap_or_else(
282-
|| {
283-
ctx.diag.push_error("Cannot parse string literal".into(), &node);
284-
Self::Invalid
285-
},
286-
)
287-
})
288-
})
289-
.or_else(|| {
290-
node.child_text(SyntaxKind::NumberLiteral)
291-
.map(crate::literals::parse_number_literal)
292-
.transpose()
293-
.unwrap_or_else(|e| {
294-
ctx.diag.push_error(e.to_string(), &node);
295-
Some(Self::Invalid)
296-
})
297-
})
298-
.or_else(|| {
299-
node.child_text(SyntaxKind::ColorLiteral).map(|s| {
300-
crate::literals::parse_color_literal(&s)
301-
.map(|i| Expression::Cast {
302-
from: Box::new(Expression::NumberLiteral(i as _, Unit::None)),
303-
to: Type::Color,
304-
})
305-
.unwrap_or_else(|| {
306-
ctx.diag.push_error("Invalid color literal".into(), &node);
307-
Self::Invalid
308-
})
309-
})
310-
})
311-
.or_else(|| {
312-
node.FunctionCallExpression().map(|n| Self::from_function_call_node(n, ctx))
313-
})
314-
.or_else(|| node.MemberAccess().map(|n| Self::from_member_access_node(n, ctx)))
315-
.or_else(|| node.IndexExpression().map(|n| Self::from_index_expression_node(n, ctx)))
316-
.or_else(|| node.SelfAssignment().map(|n| Self::from_self_assignment_node(n, ctx)))
317-
.or_else(|| node.BinaryExpression().map(|n| Self::from_binary_expression_node(n, ctx)))
318-
.or_else(|| {
319-
node.UnaryOpExpression().map(|n| Self::from_unaryop_expression_node(n, ctx))
320-
})
321-
.or_else(|| {
322-
node.ConditionalExpression().map(|n| Self::from_conditional_expression_node(n, ctx))
282+
SyntaxKind::FunctionCallExpression => {
283+
Some(Self::from_function_call_node(node.into(), ctx))
284+
}
285+
SyntaxKind::MemberAccess => {
286+
Some(Self::from_member_access_node(node.into(), ctx))
287+
}
288+
SyntaxKind::IndexExpression => {
289+
Some(Self::from_index_expression_node(node.into(), ctx))
290+
}
291+
SyntaxKind::SelfAssignment => {
292+
Some(Self::from_self_assignment_node(node.into(), ctx))
293+
}
294+
SyntaxKind::BinaryExpression => {
295+
Some(Self::from_binary_expression_node(node.into(), ctx))
296+
}
297+
SyntaxKind::UnaryOpExpression => {
298+
Some(Self::from_unaryop_expression_node(node.into(), ctx))
299+
}
300+
SyntaxKind::ConditionalExpression => {
301+
Some(Self::from_conditional_expression_node(node.into(), ctx))
302+
}
303+
SyntaxKind::ObjectLiteral => {
304+
Some(Self::from_object_literal_node(node.into(), ctx))
305+
}
306+
SyntaxKind::Array => Some(Self::from_array_node(node.into(), ctx)),
307+
SyntaxKind::CodeBlock => Some(Self::from_codeblock_node(node.into(), ctx)),
308+
SyntaxKind::StringTemplate => {
309+
Some(Self::from_string_template_node(node.into(), ctx))
310+
}
311+
_ => None,
312+
},
313+
NodeOrToken::Token(token) => match token.kind() {
314+
SyntaxKind::StringLiteral => Some(
315+
crate::literals::unescape_string(token.text())
316+
.map(Self::StringLiteral)
317+
.unwrap_or_else(|| {
318+
ctx.diag.push_error("Cannot parse string literal".into(), &token);
319+
Self::Invalid
320+
}),
321+
),
322+
SyntaxKind::NumberLiteral => Some(
323+
crate::literals::parse_number_literal(token.text().into()).unwrap_or_else(
324+
|e| {
325+
ctx.diag.push_error(e.to_string(), &node);
326+
Self::Invalid
327+
},
328+
),
329+
),
330+
SyntaxKind::ColorLiteral => Some(
331+
crate::literals::parse_color_literal(token.text())
332+
.map(|i| Expression::Cast {
333+
from: Box::new(Expression::NumberLiteral(i as _, Unit::None)),
334+
to: Type::Color,
335+
})
336+
.unwrap_or_else(|| {
337+
ctx.diag.push_error("Invalid color literal".into(), &node);
338+
Self::Invalid
339+
}),
340+
),
341+
342+
_ => None,
343+
},
323344
})
324-
.or_else(|| node.ObjectLiteral().map(|n| Self::from_object_literal_node(n, ctx)))
325-
.or_else(|| node.Array().map(|n| Self::from_array_node(n, ctx)))
326-
.or_else(|| node.CodeBlock().map(|n| Self::from_codeblock_node(n, ctx)))
327-
.or_else(|| node.StringTemplate().map(|n| Self::from_string_template_node(n, ctx)))
328345
.unwrap_or(Self::Invalid)
329346
}
330347

@@ -981,12 +998,16 @@ impl Expression {
981998
) -> Expression {
982999
let (lhs_n, rhs_n) = node.Expression();
9831000
let mut lhs = Self::from_expression_node(lhs_n.clone(), ctx);
984-
let op = None
985-
.or_else(|| node.child_token(SyntaxKind::PlusEqual).and(Some('+')))
986-
.or_else(|| node.child_token(SyntaxKind::MinusEqual).and(Some('-')))
987-
.or_else(|| node.child_token(SyntaxKind::StarEqual).and(Some('*')))
988-
.or_else(|| node.child_token(SyntaxKind::DivEqual).and(Some('/')))
989-
.or_else(|| node.child_token(SyntaxKind::Equal).and(Some('=')))
1001+
let op = node
1002+
.children_with_tokens()
1003+
.find_map(|n| match n.kind() {
1004+
SyntaxKind::PlusEqual => Some('+'),
1005+
SyntaxKind::MinusEqual => Some('-'),
1006+
SyntaxKind::StarEqual => Some('*'),
1007+
SyntaxKind::DivEqual => Some('/'),
1008+
SyntaxKind::Equal => Some('='),
1009+
_ => None,
1010+
})
9901011
.unwrap_or('_');
9911012
if lhs.ty() != Type::Invalid {
9921013
lhs.try_set_rw(ctx, if op == '=' { "Assignment" } else { "Self assignment" }, &node);
@@ -1020,19 +1041,23 @@ impl Expression {
10201041
node: syntax_nodes::BinaryExpression,
10211042
ctx: &mut LookupCtx,
10221043
) -> Expression {
1023-
let op = None
1024-
.or_else(|| node.child_token(SyntaxKind::Plus).and(Some('+')))
1025-
.or_else(|| node.child_token(SyntaxKind::Minus).and(Some('-')))
1026-
.or_else(|| node.child_token(SyntaxKind::Star).and(Some('*')))
1027-
.or_else(|| node.child_token(SyntaxKind::Div).and(Some('/')))
1028-
.or_else(|| node.child_token(SyntaxKind::LessEqual).and(Some('≤')))
1029-
.or_else(|| node.child_token(SyntaxKind::GreaterEqual).and(Some('≥')))
1030-
.or_else(|| node.child_token(SyntaxKind::LAngle).and(Some('<')))
1031-
.or_else(|| node.child_token(SyntaxKind::RAngle).and(Some('>')))
1032-
.or_else(|| node.child_token(SyntaxKind::EqualEqual).and(Some('=')))
1033-
.or_else(|| node.child_token(SyntaxKind::NotEqual).and(Some('!')))
1034-
.or_else(|| node.child_token(SyntaxKind::AndAnd).and(Some('&')))
1035-
.or_else(|| node.child_token(SyntaxKind::OrOr).and(Some('|')))
1044+
let op = node
1045+
.children_with_tokens()
1046+
.find_map(|n| match n.kind() {
1047+
SyntaxKind::Plus => Some('+'),
1048+
SyntaxKind::Minus => Some('-'),
1049+
SyntaxKind::Star => Some('*'),
1050+
SyntaxKind::Div => Some('/'),
1051+
SyntaxKind::LessEqual => Some('≤'),
1052+
SyntaxKind::GreaterEqual => Some('≥'),
1053+
SyntaxKind::LAngle => Some('<'),
1054+
SyntaxKind::RAngle => Some('>'),
1055+
SyntaxKind::EqualEqual => Some('='),
1056+
SyntaxKind::NotEqual => Some('!'),
1057+
SyntaxKind::AndAnd => Some('&'),
1058+
SyntaxKind::OrOr => Some('|'),
1059+
_ => None,
1060+
})
10361061
.unwrap_or('_');
10371062

10381063
let (lhs_n, rhs_n) = node.Expression();
@@ -1115,10 +1140,14 @@ impl Expression {
11151140
let exp_n = node.Expression();
11161141
let exp = Self::from_expression_node(exp_n, ctx);
11171142

1118-
let op = None
1119-
.or_else(|| node.child_token(SyntaxKind::Plus).and(Some('+')))
1120-
.or_else(|| node.child_token(SyntaxKind::Minus).and(Some('-')))
1121-
.or_else(|| node.child_token(SyntaxKind::Bang).and(Some('!')))
1143+
let op = node
1144+
.children_with_tokens()
1145+
.find_map(|n| match n.kind() {
1146+
SyntaxKind::Plus => Some('+'),
1147+
SyntaxKind::Minus => Some('-'),
1148+
SyntaxKind::Bang => Some('!'),
1149+
_ => None,
1150+
})
11221151
.unwrap_or('_');
11231152

11241153
let exp = match op {

0 commit comments

Comments
 (0)