Skip to content

Commit

Permalink
Add transform function
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Apr 29, 2024
1 parent b3a18e9 commit 28f1313
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
16 changes: 14 additions & 2 deletions crates/oxc_ast/src/ast/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use serde::Serialize;
#[cfg(feature = "serialize")]
use tsify::Tsify;

use crate::traverse::{SharedBox, SharedVec};
use crate::{dummy, traverse::ast::*};
use crate::dummy;
use crate::traverse::{ast::*, SharedBox, SharedVec, Token, Traverse, TraverseCtx};

use super::inherit_variants;
use super::{jsx::*, literal::*, ts::*};
Expand All @@ -41,6 +41,18 @@ export interface FormalParameterRest extends Span {
}
"#;

/// Traverse AST.
#[allow(unused_variables)] // TODO: Remove this attr once function is implemented
pub fn traverse<'a, T: Traverse<'a>>(
traverser: &mut T,
program: SharedBox<'a, TraversableProgram<'a>>,
ctx: &mut TraverseCtx<'a>,
tk: &mut Token,
) {
// TODO
// walk_traversable_program(traverser, program, ctx, tk);
}

#[ast_node]
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
Expand Down
48 changes: 45 additions & 3 deletions crates/oxc_ast/src/traverse/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,52 @@

use oxc_allocator::Allocator;

use super::{Ancestor, AstBuilder, SharedBox};
use super::{ast::TraversableProgram, Ancestor, AstBuilder, GCell, SharedBox, Token, Traverse};
use crate::ast::{traverse, Program as StandardProgram};

pub fn transform() {
// TODO
/// Run transform visitor on AST.
///
/// The provided transformer must implement `Traverse` and will be run on a version of the AST
/// with interior mutability, allowing traversal in any direction (up or down).
/// Once the transform is finished, caller can continue to use the standard version of the AST
/// in the usual way, without interior mutability.
#[allow(unsafe_code)]
pub fn transform<'a, T: Traverse<'a>>(
transformer: &mut T,
program: &mut StandardProgram<'a>,
allocator: &'a Allocator,
) {
// Generate `Token` which transformer uses to access the AST.
// SAFETY: We only create one token, and it never leaves this function.
let mut token = unsafe { Token::new_unchecked() };

// Create `TraverseCtx` which transformer uses to read ancestry
let mut ctx = TraverseCtx::new(allocator);

// Convert AST to traversable version.
//
// SAFETY: All standard and traversable AST types are mirrors of each other, with identical layouts.
// This is ensured by `#[repr(C)]` on all types. Therefore one can safely be transmuted to the other.
// As we hold a `&mut` reference to the AST, it's guaranteed there are no other live references.
// We extend the lifetime of ref to `TraversableProgram` to `&'a TraversableProgram`.
// This is safe because the node is in the arena, and doesn't move, so the ref is valid for `'a`.
// `transformer` could smuggle refs out, but could not use them without a token which is only
// available in this function.
//
// TODO: Refs could be made invalid if the allocator is reset. Hopefully this is impossible
// because `Allocator::reset` takes a `&mut` ref to the allocator, so you can't hold any immut refs
// to data in the arena at that time. But make sure.
#[allow(clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks)]
let program = GCell::from_mut(unsafe { &mut *(program as *mut _ as *mut TraversableProgram) });

// Run transformer on the traversable AST
traverse(transformer, program, &mut ctx, &mut token);

// The access token goes out of scope at this point, which guarantees that no references
// (either mutable or immutable) to the traversable AST or the token still exist.
// If the transformer attempts to hold on to any references to the AST, or to the token,
// this will produce a compile-time error.
// Therefore, the caller can now safely continue using the `&mut Program` that they passed in.
}

/// Traverse context.
Expand Down

0 comments on commit 28f1313

Please sign in to comment.