Skip to content

Commit

Permalink
chore(ast): move ast implementations to ast_impl (#3821)
Browse files Browse the repository at this point in the history
Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
  • Loading branch information
Boshen and Boshen authored Jun 22, 2024
1 parent 5673348 commit a1b2d83
Show file tree
Hide file tree
Showing 8 changed files with 1,721 additions and 1,694 deletions.
1,534 changes: 40 additions & 1,494 deletions crates/oxc_ast/src/ast/js.rs

Large diffs are not rendered by default.

177 changes: 13 additions & 164 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
// Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]`
#![allow(non_snake_case)]

use std::{
fmt,
hash::{Hash, Hasher},
};
use std::hash::Hash;

use bitflags::bitflags;
use oxc_ast_macros::visited_node;
Expand All @@ -30,20 +27,6 @@ pub struct BooleanLiteral {
pub value: bool,
}

impl BooleanLiteral {
pub fn new(span: Span, value: bool) -> Self {
Self { span, value }
}

pub fn as_str(&self) -> &'static str {
if self.value {
"true"
} else {
"false"
}
}
}

#[visited_node]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
Expand All @@ -53,18 +36,6 @@ pub struct NullLiteral {
pub span: Span,
}

impl Hash for NullLiteral {
fn hash<H: Hasher>(&self, state: &mut H) {
None::<bool>.hash(state);
}
}

impl NullLiteral {
pub fn new(span: Span) -> Self {
Self { span }
}
}

#[visited_node]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
Expand All @@ -78,45 +49,6 @@ pub struct NumericLiteral<'a> {
pub base: NumberBase,
}

impl<'a> NumericLiteral<'a> {
pub fn new(span: Span, value: f64, raw: &'a str, base: NumberBase) -> Self {
Self { span, value, raw, base }
}

/// port from [closure compiler](https://github.com/google/closure-compiler/blob/a4c880032fba961f7a6c06ef99daa3641810bfdd/src/com/google/javascript/jscomp/base/JSCompDoubles.java#L113)
/// <https://262.ecma-international.org/5.1/#sec-9.5>
#[allow(clippy::cast_possible_truncation)] // for `as i32`
pub fn ecmascript_to_int32(num: f64) -> i32 {
// Fast path for most common case. Also covers -0.0
let int32_value = num as i32;
if (f64::from(int32_value) - num).abs() < f64::EPSILON {
return int32_value;
}

// NaN, Infinity if not included in our NumericLiteral, so we just serde(skip) step 2.

// step 3
let pos_int = num.signum() * num.abs().floor();

// step 4
let int32bit = pos_int % 2f64.powi(32);

// step5
if int32bit >= 2f64.powi(31) {
(int32bit - 2f64.powi(32)) as i32
} else {
int32bit as i32
}
}
}

impl<'a> Hash for NumericLiteral<'a> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.base.hash(state);
self.raw.hash(state);
}
}

#[visited_node]
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
Expand All @@ -129,12 +61,6 @@ pub struct BigIntLiteral<'a> {
pub base: BigintBase,
}

impl<'a> BigIntLiteral<'a> {
pub fn is_zero(&self) -> bool {
self.raw == "0n"
}
}

#[visited_node]
#[derive(Debug, Clone, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
Expand All @@ -155,10 +81,18 @@ pub struct RegExp<'a> {
pub flags: RegExpFlags,
}

impl<'a> fmt::Display for RegExp<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "/{}/{}", self.pattern, self.flags)
}
#[derive(Debug, Clone, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
pub struct EmptyObject;

#[visited_node]
#[derive(Debug, Clone, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type"))]
pub struct StringLiteral<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub value: Atom<'a>,
}

bitflags! {
Expand Down Expand Up @@ -190,88 +124,3 @@ export type RegExpFlags = {
V: 128
};
"#;

impl TryFrom<char> for RegExpFlags {
type Error = char;

fn try_from(value: char) -> Result<Self, Self::Error> {
match value {
'g' => Ok(Self::G),
'i' => Ok(Self::I),
'm' => Ok(Self::M),
's' => Ok(Self::S),
'u' => Ok(Self::U),
'y' => Ok(Self::Y),
'd' => Ok(Self::D),
'v' => Ok(Self::V),
_ => Err(value),
}
}
}

impl fmt::Display for RegExpFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.contains(Self::G) {
write!(f, "g")?;
}
if self.contains(Self::I) {
write!(f, "i")?;
}
if self.contains(Self::M) {
write!(f, "m")?;
}
if self.contains(Self::S) {
write!(f, "s")?;
}
if self.contains(Self::U) {
write!(f, "u")?;
}
if self.contains(Self::Y) {
write!(f, "y")?;
}
if self.contains(Self::D) {
write!(f, "d")?;
}
if self.contains(Self::V) {
write!(f, "v")?;
}
Ok(())
}
}

#[derive(Debug, Clone, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
pub struct EmptyObject;

#[visited_node]
#[derive(Debug, Clone, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type"))]
pub struct StringLiteral<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub value: Atom<'a>,
}

impl<'a> StringLiteral<'a> {
pub fn new(span: Span, value: Atom<'a>) -> Self {
Self { span, value }
}

/// Static Semantics: `IsStringWellFormedUnicode`
/// test for \uD800-\uDFFF
pub fn is_string_well_formed_unicode(&self) -> bool {
let mut chars = self.value.chars();
while let Some(c) = chars.next() {
if c == '\\' && chars.next() == Some('u') {
let hex = &chars.as_str()[..4];
if let Ok(hex) = u32::from_str_radix(hex, 16) {
if (0xd800..=0xdfff).contains(&hex) {
return false;
}
};
}
}
true
}
}
Loading

0 comments on commit a1b2d83

Please sign in to comment.