feat(data_structures): add oxc_data_structures crate; add stack (#6206)

This commit is contained in:
Boshen 2024-10-01 10:02:45 +00:00
parent 788e444c1f
commit c3c3447ac3
15 changed files with 83 additions and 29 deletions

9
Cargo.lock generated
View file

@ -1569,6 +1569,13 @@ dependencies = [
"walkdir",
]
[[package]]
name = "oxc_data_structures"
version = "0.30.5"
dependencies = [
"assert-unchecked",
]
[[package]]
name = "oxc_diagnostics"
version = "0.30.5"
@ -1985,7 +1992,6 @@ dependencies = [
name = "oxc_transformer"
version = "0.30.5"
dependencies = [
"assert-unchecked",
"base64",
"cow-utils",
"dashmap 6.0.1",
@ -1994,6 +2000,7 @@ dependencies = [
"oxc_allocator",
"oxc_ast",
"oxc_codegen",
"oxc_data_structures",
"oxc_diagnostics",
"oxc_parser",
"oxc_regular_expression",

View file

@ -82,6 +82,7 @@ oxc_ast = { version = "0.30.5", path = "crates/oxc_ast" }
oxc_ast_macros = { version = "0.30.5", path = "crates/oxc_ast_macros" }
oxc_cfg = { version = "0.30.5", path = "crates/oxc_cfg" }
oxc_codegen = { version = "0.30.5", path = "crates/oxc_codegen" }
oxc_data_structures = { version = "0.30.5", path = "crates/oxc_data_structures" }
oxc_diagnostics = { version = "0.30.5", path = "crates/oxc_diagnostics" }
oxc_index = { version = "0.30.5", path = "crates/oxc_index" }
oxc_isolated_declarations = { version = "0.30.5", path = "crates/oxc_isolated_declarations" }

View file

@ -0,0 +1,24 @@
[package]
name = "oxc_data_structures"
version = "0.30.5"
authors.workspace = true
categories.workspace = true
edition.workspace = true
homepage.workspace = true
include = ["/src"]
keywords.workspace = true
license.workspace = true
publish = true
repository.workspace = true
rust-version.workspace = true
description.workspace = true
[lints]
workspace = true
[lib]
test = true
doctest = false
[dependencies]
assert-unchecked = { workspace = true }

View file

@ -0,0 +1 @@
pub mod stack;

View file

@ -132,7 +132,8 @@ impl<T> NonEmptyStack<T> {
/// # Panics
/// Panics if `T` is a zero-sized type.
///
/// # SAFETY
/// # Safety
///
/// * `capacity` must not be 0.
/// * `capacity` must not exceed [`Self::MAX_CAPACITY`].
#[inline]
@ -253,8 +254,9 @@ impl<T> NonEmptyStack<T> {
/// Pop value from stack, without checking that stack isn't empty.
///
/// # SAFETY
/// Stack must have at least 2 entries, so that after pop, it still has at least 1.
/// # Safety
///
/// * Stack must have at least 2 entries, so that after pop, it still has at least 1.
#[inline]
pub unsafe fn pop_unchecked(&mut self) -> T {
debug_assert!(self.cursor > self.start);
@ -284,6 +286,11 @@ impl<T> NonEmptyStack<T> {
offset + 1
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Get capacity.
#[inline]
pub fn capacity(&self) -> usize {

View file

@ -30,11 +30,16 @@ pub struct SparseStack<T> {
values: Stack<T>,
}
impl<T> Default for SparseStack<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> SparseStack<T> {
/// Maximum capacity for entries (either `Some` or `None`).
///
/// Effectively unlimited on 64-bit systems.
#[expect(dead_code)]
pub const MAX_TOTAL_CAPACITY: usize = NonEmptyStack::<bool>::MAX_CAPACITY;
/// Maximum capacity for filled entries (`Some`).
@ -44,7 +49,6 @@ impl<T> SparseStack<T> {
/// Both are effectively unlimited on 64-bit systems.
///
/// [`MAX_TOTAL_CAPACITY`]: Self::MAX_TOTAL_CAPACITY
#[expect(dead_code)]
pub const MAX_FILLED_CAPACITY: usize = Stack::<T>::MAX_CAPACITY;
/// Create new `SparseStack`.
@ -70,7 +74,6 @@ impl<T> SparseStack<T> {
/// * `total_capacity` must not exceed `Self::MAX_TOTAL_CAPACITY`.
/// * `filled_capacity` must not exceed `Self::MAX_FILLED_CAPACITY`.
#[inline]
#[expect(dead_code)]
pub fn with_capacity(total_capacity: usize, filled_capacity: usize) -> Self {
Self {
has_values: NonEmptyStack::with_capacity(total_capacity, false),
@ -187,11 +190,15 @@ impl<T> SparseStack<T> {
self.has_values.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.has_values.len() == 0
}
/// Get capacity of stack for any entries (either `Some` or `None`).
///
/// Capacity is always at least 1. Stack is never empty.
#[inline]
#[expect(dead_code)]
pub fn total_capacity(&self) -> usize {
self.has_values.capacity()
}
@ -202,7 +209,6 @@ impl<T> SparseStack<T> {
///
/// [`total_capacity`]: Self::total_capacity
#[inline]
#[expect(dead_code)]
pub fn filled_capacity(&self) -> usize {
self.values.capacity()
}

View file

@ -36,6 +36,12 @@ pub struct Stack<T> {
end: NonNull<T>,
}
impl<T> Default for Stack<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> StackCapacity<T> for Stack<T> {}
impl<T> StackCommon<T> for Stack<T> {
@ -117,7 +123,8 @@ impl<T> Stack<T> {
/// # Panics
/// Panics if `T` is a zero-sized type.
///
/// # SAFETY
/// # Safety
///
/// * `capacity` must not be 0.
/// * `capacity` must not exceed [`Self::MAX_CAPACITY`].
#[inline]
@ -154,7 +161,6 @@ impl<T> Stack<T> {
/// Get reference to last value on stack.
#[inline]
#[cfg_attr(not(test), expect(dead_code))]
pub fn last(&self) -> Option<&T> {
#[expect(clippy::if_not_else)]
if !self.is_empty() {
@ -167,8 +173,9 @@ impl<T> Stack<T> {
/// Get reference to last value on stack, without checking stack isn't empty.
///
/// # SAFETY
/// Stack must not be empty.
/// # Safety
///
/// * Stack must not be empty.
#[inline]
pub unsafe fn last_unchecked(&self) -> &T {
debug_assert!(self.end > self.start);
@ -182,7 +189,6 @@ impl<T> Stack<T> {
/// Get mutable reference to last value on stack.
#[inline]
#[cfg_attr(not(test), expect(dead_code))]
pub fn last_mut(&mut self) -> Option<&mut T> {
#[expect(clippy::if_not_else)]
if !self.is_empty() {
@ -195,8 +201,9 @@ impl<T> Stack<T> {
/// Get mutable reference to last value on stack, without checking stack isn't empty.
///
/// # SAFETY
/// Stack must not be empty.
/// # Safety
///
/// * Stack must not be empty.
#[inline]
pub unsafe fn last_mut_unchecked(&mut self) -> &mut T {
debug_assert!(self.end > self.start);
@ -265,7 +272,6 @@ impl<T> Stack<T> {
/// Pop value from stack.
#[inline]
#[cfg_attr(not(test), expect(dead_code))]
pub fn pop(&mut self) -> Option<T> {
#[expect(clippy::if_not_else)]
if !self.is_empty() {
@ -278,8 +284,9 @@ impl<T> Stack<T> {
/// Pop value from stack, without checking that stack isn't empty.
///
/// # SAFETY
/// Stack must not be empty.
/// # Safety
///
/// * Stack must not be empty.
#[inline]
pub unsafe fn pop_unchecked(&mut self) -> T {
debug_assert!(self.end > self.start);

View file

@ -21,8 +21,14 @@ test = true
doctest = false
[dependencies]
base64 = { workspace = true }
cow-utils = { workspace = true }
dashmap = { workspace = true }
indexmap = { workspace = true }
oxc-browserslist = { workspace = true }
oxc_allocator = { workspace = true }
oxc_ast = { workspace = true }
oxc_data_structures = { workspace = true }
oxc_diagnostics = { workspace = true }
oxc_parser = { workspace = true }
oxc_regular_expression = { workspace = true }
@ -30,13 +36,6 @@ oxc_semantic = { workspace = true }
oxc_span = { workspace = true }
oxc_syntax = { workspace = true, features = ["to_js_string"] }
oxc_traverse = { workspace = true }
assert-unchecked = { workspace = true }
base64 = { workspace = true }
cow-utils = { workspace = true }
dashmap = { workspace = true }
indexmap = { workspace = true }
oxc-browserslist = { workspace = true }
ropey = { workspace = true }
rustc-hash = { workspace = true }
serde = { workspace = true, features = ["derive"] }

View file

@ -16,11 +16,12 @@ use std::cell::RefCell;
use oxc_allocator::Vec;
use oxc_ast::{ast::*, NONE};
use oxc_data_structures::stack::SparseStack;
use oxc_span::SPAN;
use oxc_syntax::symbol::SymbolId;
use oxc_traverse::{Traverse, TraverseCtx};
use crate::{helpers::stack::SparseStack, TransformCtx};
use crate::TransformCtx;
/// Transform that maintains the stack of `Vec<VariableDeclarator>`s, and adds a `var` statement
/// to top of a statement block if another transform has requested that.

View file

@ -123,15 +123,17 @@
use oxc_allocator::Vec;
use oxc_ast::{ast::*, NONE};
use oxc_data_structures::stack::SparseStack;
use oxc_span::SPAN;
use oxc_syntax::{
scope::{ScopeFlags, ScopeId},
symbol::SymbolFlags,
};
use oxc_traverse::{Ancestor, Traverse, TraverseCtx};
use serde::Deserialize;
use crate::helpers::{bindings::BoundIdentifier, stack::SparseStack};
use crate::helpers::bindings::BoundIdentifier;
#[derive(Debug, Default, Clone, Deserialize)]
pub struct ArrowFunctionsOptions {

View file

@ -31,7 +31,6 @@ mod plugins;
mod helpers {
pub mod bindings;
pub mod stack;
}
use std::path::Path;