mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-13 07:32:20 +00:00
templater: move boxing to ExpressionKind variants to make the enum smaller
I'm trying to extract generic alias substitution functions, and some of them will take ExpressionKind or Box<FunctionCallNode> by value, then return it or substituted value of the same type. The cost of moving values wouldn't matter in practice, but I think it's better to keep the value types small. Now ExpressionKind is 4-word long.
This commit is contained in:
parent
fe9daac483
commit
e87b49ccc1
1 changed files with 31 additions and 26 deletions
|
@ -261,9 +261,9 @@ pub enum ExpressionKind<'i> {
|
||||||
Unary(UnaryOp, Box<ExpressionNode<'i>>),
|
Unary(UnaryOp, Box<ExpressionNode<'i>>),
|
||||||
Binary(BinaryOp, Box<ExpressionNode<'i>>, Box<ExpressionNode<'i>>),
|
Binary(BinaryOp, Box<ExpressionNode<'i>>, Box<ExpressionNode<'i>>),
|
||||||
Concat(Vec<ExpressionNode<'i>>),
|
Concat(Vec<ExpressionNode<'i>>),
|
||||||
FunctionCall(FunctionCallNode<'i>),
|
FunctionCall(Box<FunctionCallNode<'i>>),
|
||||||
MethodCall(MethodCallNode<'i>),
|
MethodCall(Box<MethodCallNode<'i>>),
|
||||||
Lambda(LambdaNode<'i>),
|
Lambda(Box<LambdaNode<'i>>),
|
||||||
/// Identity node to preserve the span in the source template text.
|
/// Identity node to preserve the span in the source template text.
|
||||||
AliasExpanded(TemplateAliasId<'i>, Box<ExpressionNode<'i>>),
|
AliasExpanded(TemplateAliasId<'i>, Box<ExpressionNode<'i>>),
|
||||||
}
|
}
|
||||||
|
@ -294,7 +294,7 @@ pub struct FunctionCallNode<'i> {
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct MethodCallNode<'i> {
|
pub struct MethodCallNode<'i> {
|
||||||
pub object: Box<ExpressionNode<'i>>,
|
pub object: ExpressionNode<'i>,
|
||||||
pub function: FunctionCallNode<'i>,
|
pub function: FunctionCallNode<'i>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ pub struct MethodCallNode<'i> {
|
||||||
pub struct LambdaNode<'i> {
|
pub struct LambdaNode<'i> {
|
||||||
pub params: Vec<&'i str>,
|
pub params: Vec<&'i str>,
|
||||||
pub params_span: pest::Span<'i>,
|
pub params_span: pest::Span<'i>,
|
||||||
pub body: Box<ExpressionNode<'i>>,
|
pub body: ExpressionNode<'i>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_identifier_or_literal(pair: Pair<Rule>) -> ExpressionKind {
|
fn parse_identifier_or_literal(pair: Pair<Rule>) -> ExpressionKind {
|
||||||
|
@ -372,7 +372,7 @@ fn parse_lambda_node(pair: Pair<Rule>) -> TemplateParseResult<LambdaNode> {
|
||||||
Ok(LambdaNode {
|
Ok(LambdaNode {
|
||||||
params,
|
params,
|
||||||
params_span,
|
params_span,
|
||||||
body: Box::new(body),
|
body,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,11 +400,11 @@ fn parse_term_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
|
||||||
}
|
}
|
||||||
Rule::identifier => ExpressionNode::new(parse_identifier_or_literal(expr), span),
|
Rule::identifier => ExpressionNode::new(parse_identifier_or_literal(expr), span),
|
||||||
Rule::function => {
|
Rule::function => {
|
||||||
let function = parse_function_call_node(expr)?;
|
let function = Box::new(parse_function_call_node(expr)?);
|
||||||
ExpressionNode::new(ExpressionKind::FunctionCall(function), span)
|
ExpressionNode::new(ExpressionKind::FunctionCall(function), span)
|
||||||
}
|
}
|
||||||
Rule::lambda => {
|
Rule::lambda => {
|
||||||
let lambda = parse_lambda_node(expr)?;
|
let lambda = Box::new(parse_lambda_node(expr)?);
|
||||||
ExpressionNode::new(ExpressionKind::Lambda(lambda), span)
|
ExpressionNode::new(ExpressionKind::Lambda(lambda), span)
|
||||||
}
|
}
|
||||||
Rule::template => parse_template_node(expr)?,
|
Rule::template => parse_template_node(expr)?,
|
||||||
|
@ -413,10 +413,10 @@ fn parse_term_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
|
||||||
inner.try_fold(primary, |object, chain| {
|
inner.try_fold(primary, |object, chain| {
|
||||||
assert_eq!(chain.as_rule(), Rule::function);
|
assert_eq!(chain.as_rule(), Rule::function);
|
||||||
let span = object.span.start_pos().span(&chain.as_span().end_pos());
|
let span = object.span.start_pos().span(&chain.as_span().end_pos());
|
||||||
let method = MethodCallNode {
|
let method = Box::new(MethodCallNode {
|
||||||
object: Box::new(object),
|
object,
|
||||||
function: parse_function_call_node(chain)?,
|
function: parse_function_call_node(chain)?,
|
||||||
};
|
});
|
||||||
Ok(ExpressionNode::new(
|
Ok(ExpressionNode::new(
|
||||||
ExpressionKind::MethodCall(method),
|
ExpressionKind::MethodCall(method),
|
||||||
span,
|
span,
|
||||||
|
@ -703,24 +703,26 @@ pub fn expand_aliases<'i>(
|
||||||
let locals = params.iter().map(|s| s.as_str()).zip(args).collect();
|
let locals = params.iter().map(|s| s.as_str()).zip(args).collect();
|
||||||
expand_defn(id, defn, &locals, node.span, state)
|
expand_defn(id, defn, &locals, node.span, state)
|
||||||
} else {
|
} else {
|
||||||
node.kind =
|
let function = Box::new(expand_function_call(*function, state)?);
|
||||||
ExpressionKind::FunctionCall(expand_function_call(function, state)?);
|
node.kind = ExpressionKind::FunctionCall(function);
|
||||||
Ok(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExpressionKind::MethodCall(method) => {
|
ExpressionKind::MethodCall(method) => {
|
||||||
node.kind = ExpressionKind::MethodCall(MethodCallNode {
|
let method = Box::new(MethodCallNode {
|
||||||
object: Box::new(expand_node(*method.object, state)?),
|
object: expand_node(method.object, state)?,
|
||||||
function: expand_function_call(method.function, state)?,
|
function: expand_function_call(method.function, state)?,
|
||||||
});
|
});
|
||||||
|
node.kind = ExpressionKind::MethodCall(method);
|
||||||
Ok(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
ExpressionKind::Lambda(lambda) => {
|
ExpressionKind::Lambda(lambda) => {
|
||||||
node.kind = ExpressionKind::Lambda(LambdaNode {
|
let lambda = Box::new(LambdaNode {
|
||||||
params: lambda.params,
|
params: lambda.params,
|
||||||
params_span: lambda.params_span,
|
params_span: lambda.params_span,
|
||||||
body: Box::new(expand_node(*lambda.body, state)?),
|
body: expand_node(lambda.body, state)?,
|
||||||
});
|
});
|
||||||
|
node.kind = ExpressionKind::Lambda(lambda);
|
||||||
Ok(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
ExpressionKind::AliasExpanded(id, subst) => {
|
ExpressionKind::AliasExpanded(id, subst) => {
|
||||||
|
@ -973,20 +975,23 @@ mod tests {
|
||||||
}
|
}
|
||||||
ExpressionKind::Concat(nodes) => ExpressionKind::Concat(normalize_list(nodes)),
|
ExpressionKind::Concat(nodes) => ExpressionKind::Concat(normalize_list(nodes)),
|
||||||
ExpressionKind::FunctionCall(function) => {
|
ExpressionKind::FunctionCall(function) => {
|
||||||
ExpressionKind::FunctionCall(normalize_function_call(function))
|
let function = Box::new(normalize_function_call(*function));
|
||||||
|
ExpressionKind::FunctionCall(function)
|
||||||
}
|
}
|
||||||
ExpressionKind::MethodCall(method) => {
|
ExpressionKind::MethodCall(method) => {
|
||||||
let object = Box::new(normalize_tree(*method.object));
|
let method = Box::new(MethodCallNode {
|
||||||
let function = normalize_function_call(method.function);
|
object: normalize_tree(method.object),
|
||||||
ExpressionKind::MethodCall(MethodCallNode { object, function })
|
function: normalize_function_call(method.function),
|
||||||
|
});
|
||||||
|
ExpressionKind::MethodCall(method)
|
||||||
}
|
}
|
||||||
ExpressionKind::Lambda(lambda) => {
|
ExpressionKind::Lambda(lambda) => {
|
||||||
let body = Box::new(normalize_tree(*lambda.body));
|
let lambda = Box::new(LambdaNode {
|
||||||
ExpressionKind::Lambda(LambdaNode {
|
|
||||||
params: lambda.params,
|
params: lambda.params,
|
||||||
params_span: empty_span(),
|
params_span: empty_span(),
|
||||||
body,
|
body: normalize_tree(lambda.body),
|
||||||
})
|
});
|
||||||
|
ExpressionKind::Lambda(lambda)
|
||||||
}
|
}
|
||||||
ExpressionKind::AliasExpanded(_, subst) => normalize_tree(*subst).kind,
|
ExpressionKind::AliasExpanded(_, subst) => normalize_tree(*subst).kind,
|
||||||
};
|
};
|
||||||
|
@ -1099,7 +1104,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_lambda_syntax() {
|
fn test_lambda_syntax() {
|
||||||
fn unwrap_lambda(node: ExpressionNode<'_>) -> LambdaNode<'_> {
|
fn unwrap_lambda(node: ExpressionNode<'_>) -> Box<LambdaNode<'_>> {
|
||||||
match node.kind {
|
match node.kind {
|
||||||
ExpressionKind::Lambda(lambda) => lambda,
|
ExpressionKind::Lambda(lambda) => lambda,
|
||||||
_ => panic!("unexpected expression: {node:?}"),
|
_ => panic!("unexpected expression: {node:?}"),
|
||||||
|
|
Loading…
Reference in a new issue