Skip to content

Commit

Permalink
refactor(parser): parse BigInt lazily
Browse files Browse the repository at this point in the history
This PR partially fixes #1803 and is part of #1800.

The BigInt value is now boxed, so it can be dropped along with the AST.

It is also removed from the `Token` value, so that the token size can be
reduced once we removed all the variants.
  • Loading branch information
Boshen committed Jan 7, 2024
1 parent f46ed71 commit ef1143c
Show file tree
Hide file tree
Showing 14 changed files with 39 additions and 36 deletions.
8 changes: 7 additions & 1 deletion crates/oxc_allocator/src/arena.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::{
self,
fmt::{self, Debug, Formatter},
fmt::{self, Debug, Display, Formatter},
hash::{Hash, Hasher},
ops, ptr,
};
Expand Down Expand Up @@ -49,6 +49,12 @@ impl<'alloc, T: ?Sized + Debug> Debug for Box<'alloc, T> {
}
}

impl<'alloc, T: ?Sized + Display> Display for Box<'alloc, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

// Unused right now.
// impl<'alloc, T> PartialEq for Box<'alloc, T>
// where
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub enum Expression<'a> {
BooleanLiteral(Box<'a, BooleanLiteral>),
NullLiteral(Box<'a, NullLiteral>),
NumberLiteral(Box<'a, NumberLiteral<'a>>),
BigintLiteral(Box<'a, BigintLiteral>),
BigintLiteral(Box<'a, BigintLiteral<'a>>),
RegExpLiteral(Box<'a, RegExpLiteral>),
StringLiteral(Box<'a, StringLiteral>),
TemplateLiteral(Box<'a, TemplateLiteral<'a>>),
Expand Down
9 changes: 6 additions & 3 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::{

use bitflags::bitflags;
use num_bigint::BigInt;

use oxc_allocator::Box;
use oxc_span::{Atom, Span};
use oxc_syntax::{BigintBase, NumberBase};
#[cfg(feature = "serde")]
Expand Down Expand Up @@ -104,13 +106,14 @@ impl<'a> Hash for NumberLiteral<'a> {
}
}

#[derive(Debug, Clone, Hash)]
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))]
pub struct BigintLiteral {
pub struct BigintLiteral<'a> {
#[cfg_attr(feature = "serde", serde(flatten))]
pub span: Span,
// Box the value so the underlying data can be dropped.
#[cfg_attr(feature = "serde", serde(serialize_with = "crate::serialize::serialize_bigint"))]
pub value: BigInt,
pub value: Box<'a, BigInt>,
#[cfg_attr(feature = "serde", serde(skip))]
pub base: BigintBase,
}
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub enum TSLiteral<'a> {
BooleanLiteral(Box<'a, BooleanLiteral>),
NullLiteral(Box<'a, NullLiteral>),
NumberLiteral(Box<'a, NumberLiteral<'a>>),
BigintLiteral(Box<'a, BigintLiteral>),
BigintLiteral(Box<'a, BigintLiteral<'a>>),
RegExpLiteral(Box<'a, RegExpLiteral>),
StringLiteral(Box<'a, StringLiteral>),
TemplateLiteral(Box<'a, TemplateLiteral<'a>>),
Expand Down
6 changes: 3 additions & 3 deletions crates/oxc_ast/src/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ impl<'a> AstBuilder<'a> {
BooleanLiteral { span, value }
}

pub fn bigint_literal(&self, span: Span, value: BigInt, base: BigintBase) -> BigintLiteral {
BigintLiteral { span, value, base }
pub fn bigint_literal(&self, span: Span, value: BigInt, base: BigintBase) -> BigintLiteral<'a> {
BigintLiteral { span, value: self.alloc(value), base }
}

pub fn template_literal(
Expand Down Expand Up @@ -187,7 +187,7 @@ impl<'a> AstBuilder<'a> {
Expression::NumberLiteral(self.alloc(literal))
}

pub fn literal_bigint_expression(&self, literal: BigintLiteral) -> Expression<'a> {
pub fn literal_bigint_expression(&self, literal: BigintLiteral<'a>) -> Expression<'a> {
Expression::BigintLiteral(self.alloc(literal))
}

Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_ast/src/ast_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub enum AstKind<'a> {
StringLiteral(&'a StringLiteral),
BooleanLiteral(&'a BooleanLiteral),
NullLiteral(&'a NullLiteral),
BigintLiteral(&'a BigintLiteral),
BigintLiteral(&'a BigintLiteral<'a>),
RegExpLiteral(&'a RegExpLiteral),
TemplateLiteral(&'a TemplateLiteral<'a>),

Expand Down Expand Up @@ -522,7 +522,7 @@ impl<'a> AstKind<'a> {
Self::StringLiteral(s) => format!("NumberLiteral({})", s.value).into(),
Self::BooleanLiteral(b) => format!("BooleanLiteral({})", b.value).into(),
Self::NullLiteral(_) => "NullLiteral".into(),
Self::BigintLiteral(b) => format!("BigintLiteral({})", b.value).into(),
Self::BigintLiteral(b) => format!("BigintLiteral({:?})", b.value).into(),
Self::RegExpLiteral(r) => format!("RegExpLiteral({})", r.regex).into(),
Self::TemplateLiteral(t) => format!(
"TemplateLiteral({})",
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1275,7 +1275,7 @@ pub trait Visit<'a>: Sized {
self.leave_node(kind);
}

fn visit_bigint_literal(&mut self, lit: &BigintLiteral) {
fn visit_bigint_literal(&mut self, lit: &BigintLiteral<'a>) {
let kind = AstKind::BigintLiteral(self.alloc(lit));
self.enter_node(kind);
self.leave_node(kind);
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/visit_mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1271,7 +1271,7 @@ pub trait VisitMut<'a>: Sized {
self.leave_node(kind);
}

fn visit_bigint_literal(&mut self, lit: &mut BigintLiteral) {
fn visit_bigint_literal(&mut self, lit: &mut BigintLiteral<'a>) {
let kind = AstKind::BigintLiteral(self.alloc(lit));
self.enter_node(kind);
self.leave_node(kind);
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,7 +1045,7 @@ fn print_non_negative_float<const MINIFY: bool>(value: f64, _p: &Codegen<{ MINIF
result
}

impl<const MINIFY: bool> Gen<MINIFY> for BigintLiteral {
impl<'a, const MINIFY: bool> Gen<MINIFY> for BigintLiteral<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
use num_bigint::Sign;

Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_formatter/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ impl<'a> Gen for NumberLiteral<'a> {
}
}

impl Gen for BigintLiteral {
impl<'a> Gen for BigintLiteral<'a> {
fn gen(&self, p: &mut Formatter) {
p.print_str(self.value.to_string().as_bytes());
p.print(b'n');
Expand Down
13 changes: 7 additions & 6 deletions crates/oxc_parser/src/js/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use super::{
};
use crate::{
diagnostics,
lexer::parse_big_int,
lexer::{Kind, TokenValue},
list::SeparatedList,
Context, Parser,
Expand Down Expand Up @@ -297,7 +298,7 @@ impl<'a> Parser<'a> {
Ok(NumberLiteral::new(self.end_span(span), value, raw, base))
}

pub(crate) fn parse_literal_bigint(&mut self) -> Result<BigintLiteral> {
pub(crate) fn parse_literal_bigint(&mut self) -> Result<BigintLiteral<'a>> {
let span = self.start_span();
let base = match self.cur_kind() {
Kind::Decimal => BigintBase::Decimal,
Expand All @@ -306,12 +307,12 @@ impl<'a> Parser<'a> {
Kind::Hex => BigintBase::Hex,
_ => return Err(self.unexpected()),
};
let value = match self.cur_kind() {
kind if kind.is_number() => self.cur_token().value.as_bigint(),
_ => return Err(self.unexpected()),
};
let token = self.cur_token();
let src = self.cur_src().strip_suffix('n').unwrap();
let value = parse_big_int(src, token.kind)
.map_err(|err| diagnostics::InvalidNumber(err, token.span()))?;
self.bump_any();
Ok(BigintLiteral { span: self.end_span(span), value, base })
Ok(self.ast.bigint_literal(self.end_span(span), value, base))
}

pub(crate) fn parse_literal_regexp(&mut self) -> Result<RegExpLiteral> {
Expand Down
13 changes: 7 additions & 6 deletions crates/oxc_parser/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ use oxc_syntax::{
};
pub use token::{RegExp, Token, TokenValue};

pub use self::kind::Kind;
pub use self::{kind::Kind, number::parse_big_int};
use self::{
number::{parse_big_int, parse_float, parse_int},
number::{parse_float, parse_int},
string_builder::AutoCow,
trivia_builder::TriviaBuilder,
};
Expand Down Expand Up @@ -299,10 +299,11 @@ impl<'a> Lexer<'a> {
fn set_numeric_value(&mut self, kind: Kind, src: &'a str) {
let value = match kind {
Kind::Decimal | Kind::Binary | Kind::Octal | Kind::Hex => {
src.strip_suffix('n').map_or_else(
|| parse_int(src, kind).map(TokenValue::Number),
|src| parse_big_int(src, kind).map(TokenValue::BigInt),
)
if src.ends_with('n') {
// BigInt is parsed lazily in the parser
return;
}
parse_int(src, kind).map(TokenValue::Number)
}
Kind::Float | Kind::PositiveExponential | Kind::NegativeExponential => {
parse_float(src).map(TokenValue::Number)
Expand Down
8 changes: 0 additions & 8 deletions crates/oxc_parser/src/lexer/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ impl<'a> Token<'a> {
pub enum TokenValue<'a> {
None,
Number(f64),
BigInt(num_bigint::BigInt),
String(&'a str),
RegExp(RegExp<'a>),
}
Expand All @@ -67,13 +66,6 @@ impl<'a> TokenValue<'a> {
}
}

pub fn as_bigint(&self) -> num_bigint::BigInt {
match self {
Self::BigInt(s) => s.clone(),
_ => unreachable!("expected bigint!"),
}
}

pub fn as_regex(&self) -> &RegExp<'a> {
match self {
Self::RegExp(regex) => regex,
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_prettier/src/format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1291,7 +1291,7 @@ impl<'a> Format<'a> for NumberLiteral<'a> {
}
}

impl<'a> Format<'a> for BigintLiteral {
impl<'a> Format<'a> for BigintLiteral<'a> {
fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> {
let text = self.span.source_text(p.source_text);
// Perf: avoid a memory allocation from `to_ascii_lowercase`.
Expand Down

0 comments on commit ef1143c

Please sign in to comment.