Skip to content

Commit a1f1dfc

Browse files
committed
Add new simple operators &&= ||= ?? ??=
1 parent cc54e10 commit a1f1dfc

File tree

3 files changed

+73
-38
lines changed

3 files changed

+73
-38
lines changed

Cargo.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ edition = "2021"
1313
[dependencies]
1414
hash-chain = "0.3"
1515
log = "0.4"
16-
ress = "0.11"
17-
resast = "0.6.0-alpha.5"
16+
# ress = "0.11"
17+
# resast = "0.6.0-alpha.5"
18+
ress = { path = "../ress" }
19+
resast = { path = "../resast" }
1820
res-regex = "0.1"
1921
tracing = "0.1"
2022

src/spanned/mod.rs

+24-12
Original file line numberDiff line numberDiff line change
@@ -712,11 +712,9 @@ where
712712
fn parse_import_default_specifier(&mut self) -> Res<DefaultImportSpec<Cow<'b, str>>> {
713713
let start = self.look_ahead_position;
714714
let id = self.parse_ident_name()?;
715-
self.context.lexical_names.declare(
716-
id.slice.source.clone(),
717-
DeclKind::Lex(true),
718-
start,
719-
)?;
715+
self.context
716+
.lexical_names
717+
.declare(id.slice.source.clone(), DeclKind::Lex(true), start)?;
720718
Ok(DefaultImportSpec { id })
721719
}
722720

@@ -4795,7 +4793,6 @@ where
47954793
};
47964794
elements.push(ele);
47974795
}
4798-
47994796
}
48004797
}
48014798
let close_bracket = self.expect_punct(Punct::CloseBracket)?;
@@ -5070,7 +5067,7 @@ where
50705067
&item,
50715068
&[
50725069
"=", "+=", "-=", "/=", "*=", "**=", "|=", "&=", "~=", "%=", "<<=",
5073-
">>=", ">>>=",
5070+
">>=", ">>>=", "&&=", "||=", "??=",
50745071
],
50755072
);
50765073
}
@@ -5080,7 +5077,7 @@ where
50805077
&item,
50815078
&[
50825079
"=", "+=", "-=", "/=", "*=", "**=", "|=", "&=", "~=", "%=", "<<=", ">>=",
5083-
">>>=",
5080+
">>>=", "&&=", "||=", "??=",
50845081
],
50855082
);
50865083
}
@@ -5120,6 +5117,9 @@ where
51205117
Punct::CaretEqual => Some(AssignOp::XOrEqual(slice.into())),
51215118
Punct::AmpersandEqual => Some(AssignOp::AndEqual(slice.into())),
51225119
Punct::DoubleAsteriskEqual => Some(AssignOp::PowerOfEqual(slice.into())),
5120+
Punct::DoubleAmpersandEqual => Some(AssignOp::DoubleAmpersandEqual(slice.into())),
5121+
Punct::DoublePipeEqual => Some(AssignOp::DoublePipeEqual(slice.into())),
5122+
Punct::DoubleQuestionMarkEqual => Some(AssignOp::DoubleQuestionmarkEqual(slice.into())),
51235123
_ => None,
51245124
}
51255125
}
@@ -5658,6 +5658,7 @@ where
56585658
log::debug!("left: {:#?} {}", left, self.context.allow_yield);
56595659
if op.token.matches_punct(Punct::DoubleAmpersand)
56605660
|| op.token.matches_punct(Punct::DoublePipe)
5661+
|| op.token.matches_punct(Punct::DoubleQuestionMark)
56615662
{
56625663
stack.push(Expr::Logical(LogicalExpr {
56635664
operator: self.logical_operator(&op).ok_or_else(|| {
@@ -5692,6 +5693,7 @@ where
56925693
.ok_or_else(|| self.op_error("invalid binary operation, too few operators"))?;
56935694
if op.token.matches_punct(Punct::DoubleAmpersand)
56945695
|| op.token.matches_punct(Punct::DoublePipe)
5696+
|| op.token.matches_punct(Punct::DoubleQuestionMark)
56955697
{
56965698
let operator = self
56975699
.logical_operator(&op)
@@ -5855,6 +5857,7 @@ where
58555857
Token::Punct(ref p) => match p {
58565858
Punct::DoubleAmpersand => Some(LogicalOp::And(slice.into())),
58575859
Punct::DoublePipe => Some(LogicalOp::Or(slice.into())),
5860+
Punct::DoubleQuestionMark => Some(LogicalOp::NullishCoalescing(slice.into())),
58585861
_ => None,
58595862
},
58605863
_ => None,
@@ -6372,7 +6375,7 @@ where
63726375
| Punct::Comma
63736376
| Punct::Equal
63746377
| Punct::CloseBracket => 0,
6375-
Punct::DoublePipe => 1,
6378+
Punct::DoublePipe | Punct::DoubleQuestionMark => 1,
63766379
Punct::DoubleAmpersand => 2,
63776380
Punct::Pipe => 3,
63786381
Punct::Caret => 4,
@@ -6668,6 +6671,15 @@ where
66686671
|| self.look_ahead.token.matches_punct(Punct::PipeEqual)
66696672
|| self.look_ahead.token.matches_punct(Punct::CaretEqual)
66706673
|| self.look_ahead.token.matches_punct(Punct::AmpersandEqual)
6674+
|| self
6675+
.look_ahead
6676+
.token
6677+
.matches_punct(Punct::DoubleAmpersandEqual)
6678+
|| self.look_ahead.token.matches_punct(Punct::DoublePipeEqual)
6679+
|| self
6680+
.look_ahead
6681+
.token
6682+
.matches_punct(Punct::DoubleQuestionMarkEqual)
66716683
}
66726684
/// The keyword `async` is conditional, that means to decided
66736685
/// if we are actually at an async function we need to check the
@@ -6763,8 +6775,8 @@ where
67636775
let slice = self.scanner.str_for(&item.span).unwrap();
67646776
let contents = match &item.token {
67656777
Token::String(lit) => match lit {
6766-
ress::tokens::StringLit::Double(inner) => inner.content.clone(),
6767-
ress::tokens::StringLit::Single(inner) => inner.content.clone(),
6778+
ress::tokens::StringLit::Double(inner) => inner.content,
6779+
ress::tokens::StringLit::Single(inner) => inner.content,
67686780
},
67696781
_ => {
67706782
return Err(Error::UnexpectedToken(
@@ -6821,7 +6833,7 @@ where
68216833
// regex will be on 1 line if `validate` is successful
68226834
let line = item.location.start.line;
68236835
let Token::RegEx(token) = &item.token else {
6824-
return self.expected_token_error(item, &["<regex literal>"])
6836+
return self.expected_token_error(item, &["<regex literal>"]);
68256837
};
68266838
let open_slash_pos = Position {
68276839
line: line as u32,

tests/snippets.rs

+45-24
Original file line numberDiff line numberDiff line change
@@ -1283,8 +1283,8 @@ fn setter_scope() {
12831283
fn array_pattern_with_empty_entry() {
12841284
use resast::spanned::{
12851285
decl::{Decl, VarDecl, VarDecls},
1286-
pat::{ArrayPat, ArrayPatPart, Pat},
12871286
expr::Expr,
1287+
pat::{ArrayPat, ArrayPatPart, Pat},
12881288
Ident, ListEntry, Program, ProgramPart, Slice, SourceLocation, VarKind,
12891289
};
12901290
let js = "let [x,,] = y";
@@ -1298,35 +1298,36 @@ fn array_pattern_with_empty_entry() {
12981298
item: VarDecl {
12991299
id: Pat::Array(ArrayPat {
13001300
open_bracket: Position::new(1, 5).into(),
1301-
elements: vec![ListEntry {
1302-
item: Some(ArrayPatPart::Pat(Pat::Ident(Ident {
1303-
slice: Slice {
1304-
source: Cow::Borrowed("x").into(),
1305-
loc: SourceLocation {
1306-
start: Position::new(1, 6),
1307-
end: Position::new(1, 7)
1301+
elements: vec![
1302+
ListEntry {
1303+
item: Some(ArrayPatPart::Pat(Pat::Ident(Ident {
1304+
slice: Slice {
1305+
source: Cow::Borrowed("x").into(),
1306+
loc: SourceLocation {
1307+
start: Position::new(1, 6),
1308+
end: Position::new(1, 7)
1309+
}
13081310
}
1309-
}
1310-
}))),
1311-
comma: Some(Position::new(1, 7).into()),
1312-
}, ListEntry {
1313-
item: None,
1314-
comma: Some(Position::new(1, 8).into()),
1315-
}],
1311+
}))),
1312+
comma: Some(Position::new(1, 7).into()),
1313+
},
1314+
ListEntry {
1315+
item: None,
1316+
comma: Some(Position::new(1, 8).into()),
1317+
}
1318+
],
13161319
close_bracket: Position::new(1, 9).into()
13171320
}),
13181321
eq: Some(Position::new(1, 11).into()),
1319-
init: Some(Expr::Ident(
1320-
Ident {
1321-
slice: Slice {
1322-
source: Cow::Borrowed("y").into(),
1323-
loc: SourceLocation {
1324-
start: Position::new(1, 13),
1325-
end: Position::new(1, 14)
1326-
}
1322+
init: Some(Expr::Ident(Ident {
1323+
slice: Slice {
1324+
source: Cow::Borrowed("y").into(),
1325+
loc: SourceLocation {
1326+
start: Position::new(1, 13),
1327+
end: Position::new(1, 14)
13271328
}
13281329
}
1329-
)),
1330+
})),
13301331
},
13311332
comma: None
13321333
}]
@@ -1382,6 +1383,26 @@ fn call_args() {
13821383
run_spanned_test("call(/.+/, '')", false).unwrap();
13831384
}
13841385

1386+
#[test]
1387+
fn and_and_equal() {
1388+
run_spanned_test("x &&= false", false).unwrap();
1389+
}
1390+
1391+
#[test]
1392+
fn or_or_equal() {
1393+
run_spanned_test("x ||= false", false).unwrap();
1394+
}
1395+
1396+
#[test]
1397+
fn q_q_equal() {
1398+
run_spanned_test("x ??= false", false).unwrap();
1399+
}
1400+
1401+
#[test]
1402+
fn nullish_coalesce() {
1403+
run_spanned_test("b ?? false", false).unwrap();
1404+
}
1405+
13851406
fn run_test(js: &str, as_mod: bool) -> Result<(), ressa::Error> {
13861407
let p = generate_program(js, as_mod);
13871408
log::debug!("{:#?}", p);

0 commit comments

Comments
 (0)