Skip to content

Commit 083d5b5

Browse files
committed
fix(parser): repeated parsing of module blocks
1 parent e56879e commit 083d5b5

File tree

2 files changed

+60
-34
lines changed

2 files changed

+60
-34
lines changed

crates/nu-parser/src/parse_keywords.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ pub fn parse_for(working_set: &mut StateWorkingSet, lite_command: &LiteCommand)
281281
Some(decl_id) => {
282282
working_set.enter_scope();
283283
let ParsedInternalCall { call, output } =
284-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
284+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
285285

286286
working_set.exit_scope();
287287

@@ -589,6 +589,7 @@ fn parse_def_inner(
589589
Span::concat(command_spans),
590590
rest_spans,
591591
decl_id,
592+
false,
592593
);
593594
// This is to preserve the order of the errors so that
594595
// the check errors below come first
@@ -842,6 +843,7 @@ fn parse_extern_inner(
842843
Span::concat(command_spans),
843844
rest_spans,
844845
decl_id,
846+
false,
845847
);
846848
working_set.exit_scope();
847849

@@ -1103,6 +1105,7 @@ pub fn parse_alias(
11031105
Span::concat(command_spans),
11041106
rest_spans,
11051107
decl_id,
1108+
false,
11061109
);
11071110

11081111
working_set
@@ -1365,6 +1368,7 @@ pub fn parse_export_in_block(
13651368
&parts[2..]
13661369
},
13671370
decl_id,
1371+
false,
13681372
);
13691373
// don't need errors generated by parse_internal_call
13701374
// further error will be generated by detail `parse_xxx` function.
@@ -1836,7 +1840,7 @@ pub fn parse_export_env(
18361840
let call = match working_set.find_decl(b"export-env") {
18371841
Some(decl_id) => {
18381842
let ParsedInternalCall { call, output } =
1839-
parse_internal_call(working_set, spans[0], &[spans[1]], decl_id);
1843+
parse_internal_call(working_set, spans[0], &[spans[1]], decl_id, false);
18401844
let decl = working_set.get_decl(decl_id);
18411845

18421846
let call_span = Span::concat(spans);
@@ -2348,6 +2352,7 @@ pub fn parse_module(
23482352
Span::concat(command_spans),
23492353
rest_spans,
23502354
decl_id,
2355+
true,
23512356
);
23522357
let decl = working_set.get_decl(decl_id);
23532358

@@ -2385,7 +2390,11 @@ pub fn parse_module(
23852390

23862391
let (module_name_or_path, module_name_or_path_span, module_name_or_path_expr) =
23872392
if let Some(name) = call.positional_nth(0) {
2388-
if let Some(s) = name.as_string() {
2393+
// Here name is supposed to be a garbage expression
2394+
// since argument `lite` is set to true in last `parse_internal_call` call.
2395+
// Need to parse the name expression here for later override.
2396+
let name_expr = parse_string(working_set, name.span);
2397+
if let Some(s) = name_expr.as_string() {
23892398
if let Some(mod_name) = module_name {
23902399
if s.as_bytes() == mod_name {
23912400
working_set.error(ParseError::NamedAsModule(
@@ -2405,7 +2414,7 @@ pub fn parse_module(
24052414
);
24062415
}
24072416
}
2408-
(s, name.span, name.clone())
2417+
(s, name.span, name_expr)
24092418
} else {
24102419
working_set.error(ParseError::UnknownState(
24112420
"internal error: name not a string".into(),
@@ -2421,14 +2430,21 @@ pub fn parse_module(
24212430
return (garbage_pipeline(working_set, spans), None);
24222431
};
24232432

2424-
let pipeline = Pipeline::from_vec(vec![Expression::new(
2425-
working_set,
2426-
Expr::Call(call),
2427-
call_span,
2428-
Type::Any,
2429-
)]);
2430-
24312433
if spans.len() == split_id + 1 {
2434+
let call = Box::new(Call {
2435+
head: Span::concat(&spans[..split_id]),
2436+
decl_id: call.decl_id,
2437+
arguments: vec![Argument::Positional(module_name_or_path_expr)],
2438+
parser_info: HashMap::new(),
2439+
});
2440+
2441+
let pipeline = Pipeline::from_vec(vec![Expression::new(
2442+
working_set,
2443+
Expr::Call(call),
2444+
call_span,
2445+
Type::Any,
2446+
)]);
2447+
24322448
if let Some(module_id) = parse_module_file_or_dir(
24332449
working_set,
24342450
module_name_or_path.as_bytes(),
@@ -2561,6 +2577,7 @@ pub fn parse_use(
25612577
Span::concat(command_spans),
25622578
rest_spans,
25632579
decl_id,
2580+
false,
25642581
);
25652582
let decl = working_set.get_decl(decl_id);
25662583

@@ -2785,7 +2802,7 @@ pub fn parse_hide(working_set: &mut StateWorkingSet, lite_command: &LiteCommand)
27852802
let (call, args_spans) = match working_set.find_decl(b"hide") {
27862803
Some(decl_id) => {
27872804
let ParsedInternalCall { call, output } =
2788-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
2805+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
27892806
let decl = working_set.get_decl(decl_id);
27902807

27912808
let call_span = Span::concat(spans);
@@ -3399,7 +3416,7 @@ pub fn parse_let(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline
33993416
}
34003417
}
34013418
let ParsedInternalCall { call, output } =
3402-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
3419+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
34033420

34043421
return Pipeline::from_vec(vec![Expression::new(
34053422
working_set,
@@ -3560,7 +3577,7 @@ pub fn parse_const(working_set: &mut StateWorkingSet, spans: &[Span]) -> (Pipeli
35603577
}
35613578
}
35623579
let ParsedInternalCall { call, output } =
3563-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
3580+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
35643581

35653582
return (
35663583
Pipeline::from_vec(vec![Expression::new(
@@ -3682,7 +3699,7 @@ pub fn parse_mut(working_set: &mut StateWorkingSet, spans: &[Span]) -> Pipeline
36823699
}
36833700
}
36843701
let ParsedInternalCall { call, output } =
3685-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
3702+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
36863703

36873704
return Pipeline::from_vec(vec![Expression::new(
36883705
working_set,
@@ -3730,7 +3747,7 @@ pub fn parse_source(working_set: &mut StateWorkingSet, lite_command: &LiteComman
37303747
// Is this the right call to be using here?
37313748
// Some of the others (`parse_let`) use it, some of them (`parse_hide`) don't.
37323749
let ParsedInternalCall { call, output } =
3733-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
3750+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
37343751

37353752
let Ok(is_help) = has_flag_const(working_set, &call, "help") else {
37363753
return garbage_pipeline(working_set, spans);
@@ -3890,7 +3907,7 @@ pub fn parse_where_expr(working_set: &mut StateWorkingSet, spans: &[Span]) -> Ex
38903907
let call = match working_set.find_decl(b"where") {
38913908
Some(decl_id) => {
38923909
let ParsedInternalCall { call, output } =
3893-
parse_internal_call(working_set, spans[0], &spans[1..], decl_id);
3910+
parse_internal_call(working_set, spans[0], &spans[1..], decl_id, false);
38943911
let decl = working_set.get_decl(decl_id);
38953912

38963913
let call_span = Span::concat(spans);

crates/nu-parser/src/parser.rs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,7 @@ pub fn parse_internal_call(
987987
command_span: Span,
988988
spans: &[Span],
989989
decl_id: DeclId,
990+
lite: bool,
990991
) -> ParsedInternalCall {
991992
trace!("parsing: internal call (decl id: {})", decl_id.get());
992993

@@ -1269,23 +1270,29 @@ pub fn parse_internal_call(
12691270
continue;
12701271
}
12711272

1272-
let arg = parse_multispan_value(
1273-
working_set,
1274-
&spans[..end],
1275-
&mut spans_idx,
1276-
&positional.shape,
1277-
);
1278-
1279-
let arg = if !type_compatible(&positional.shape.to_type(), &arg.ty) {
1280-
working_set.error(ParseError::TypeMismatch(
1281-
positional.shape.to_type(),
1282-
arg.ty,
1283-
arg.span,
1284-
));
1285-
Expression::garbage(working_set, arg.span)
1273+
// HACK: avoid repeated parsing of argument values for special cases
1274+
// see https://github.com/nushell/nushell/issues/16398
1275+
let arg = if lite {
1276+
Expression::garbage(working_set, spans[spans_idx])
12861277
} else {
1287-
arg
1278+
let arg = parse_multispan_value(
1279+
working_set,
1280+
&spans[..end],
1281+
&mut spans_idx,
1282+
&positional.shape,
1283+
);
1284+
if !type_compatible(&positional.shape.to_type(), &arg.ty) {
1285+
working_set.error(ParseError::TypeMismatch(
1286+
positional.shape.to_type(),
1287+
arg.ty,
1288+
arg.span,
1289+
));
1290+
Expression::garbage(working_set, arg.span)
1291+
} else {
1292+
arg
1293+
}
12881294
};
1295+
12891296
call.add_positional(arg);
12901297
positional_idx += 1;
12911298
} else if signature.allows_unknown_args {
@@ -1391,6 +1398,7 @@ pub fn parse_call(working_set: &mut StateWorkingSet, spans: &[Span], head: Span)
13911398
Span::concat(&spans[cmd_start..pos]),
13921399
&spans[pos..],
13931400
decl_id,
1401+
false,
13941402
)
13951403
}
13961404
} else {
@@ -1400,6 +1408,7 @@ pub fn parse_call(working_set: &mut StateWorkingSet, spans: &[Span], head: Span)
14001408
Span::concat(&spans[cmd_start..pos]),
14011409
&spans[pos..],
14021410
decl_id,
1411+
false,
14031412
)
14041413
};
14051414

@@ -1574,12 +1583,12 @@ pub fn parse_attribute(
15741583
}
15751584
_ => {
15761585
trace!("parsing: alias of internal call");
1577-
parse_internal_call(working_set, name_span, &spans[cmd_end..], decl_id)
1586+
parse_internal_call(working_set, name_span, &spans[cmd_end..], decl_id, false)
15781587
}
15791588
},
15801589
None => {
15811590
trace!("parsing: internal call");
1582-
parse_internal_call(working_set, name_span, &spans[cmd_end..], decl_id)
1591+
parse_internal_call(working_set, name_span, &spans[cmd_end..], decl_id, false)
15831592
}
15841593
};
15851594

0 commit comments

Comments
 (0)