@@ -5,7 +5,7 @@ use std::{
55} ;
66
77use emacs:: { defun, Result , Value , Env , GlobalRef , Vector , IntoLisp , FromLisp } ;
8- use tree_sitter:: { Tree , TreeCursor } ;
8+ use tree_sitter:: { Tree , TreeCursor , Node } ;
99
1010use crate :: {
1111 types:: { self , Shared , BytePos } ,
@@ -121,7 +121,7 @@ impl<'e> FromLisp<'e> for TreeOrNode<'e> {
121121 return Ok ( Self :: Tree ( value) ) ;
122122 }
123123 if let Ok ( value) = value. into_rust ( ) {
124- return Ok ( Self :: Node ( value) )
124+ return Ok ( Self :: Node ( value) ) ;
125125 }
126126 value. env . signal ( wrong_type_argument, ( tree_or_node_p, value) )
127127 }
@@ -231,20 +231,12 @@ struct DepthFirstIterator {
231231// TODO: Provide a function to move backward.
232232impl DepthFirstIterator {
233233 fn new ( tree_or_node : TreeOrNode ) -> Self {
234- Self {
235- cursor : tree_or_node. walk ( ) ,
236- state : Start ,
237- depth : 0 ,
238- }
234+ Self { cursor : tree_or_node. walk ( ) , state : Start , depth : 0 }
239235 }
240236
241237 #[ inline]
242238 fn item ( & self ) -> Option < ( RNode , usize ) > {
243- Some ( (
244- RNode :: new ( self . cursor . clone_tree ( ) ,
245- |_| self . cursor . borrow ( ) . node ( ) ) ,
246- self . depth ,
247- ) )
239+ Some ( ( RNode :: new ( self . cursor . clone_tree ( ) , |_| self . cursor . borrow ( ) . node ( ) ) , self . depth ) )
248240 }
249241
250242 fn close ( & mut self ) {
@@ -282,7 +274,7 @@ impl Iterator for DepthFirstIterator {
282274 self . next ( )
283275 }
284276 }
285- Done => None
277+ Done => None ,
286278 }
287279 }
288280}
@@ -308,130 +300,205 @@ fn _iter_close(iterator: &mut DepthFirstIterator) -> Result<()> {
308300 Ok ( iterator. close ( ) )
309301}
310302
311- /// Retrieve properties of the node that ITERATOR is currently on.
303+ #[ derive( Clone , Copy ) ]
304+ enum VectorOrKeyword < ' e > {
305+ Vector ( Vector < ' e > ) ,
306+ Keyword ( Value < ' e > ) ,
307+ }
308+
309+ impl < ' e > FromLisp < ' e > for VectorOrKeyword < ' e > {
310+ fn from_lisp ( value : Value < ' e > ) -> Result < Self > {
311+ if let Ok ( value) = value. into_rust :: < Vector > ( ) {
312+ Ok ( Self :: Vector ( value) )
313+ } else {
314+ // TODO: Verify that it's a valid node property
315+ Ok ( Self :: Keyword ( value) )
316+ }
317+ }
318+ }
319+
320+ /// Return the properties of ITERATOR's current node, or the node itself.
321+ ///
322+ /// If PROPS is a vector of property names, return a vector containing the node's
323+ /// corresponding properties. If OUTPUT is also non-nil, it must be a vector of the
324+ /// same length, where the properties will be written into.
325+ ///
326+ /// If PROPS is a single property name, return that property.
327+ ///
328+ /// If PROPS is nil, return the node itself.
312329///
313- /// PROPS is a vector of property names to retrieve.
314- /// OUTPUT is a vector where the properties will be written to.
330+ /// See `tsc-valid-node-props' for the list of available properties.
315331#[ defun]
316- fn _iter_current_node ( iterator : & mut DepthFirstIterator , props : Vector , output : Vector ) -> Result < ( ) > {
317- let env = output. value ( ) . env ;
332+ fn _iter_current_node < ' e > (
333+ iterator : & mut DepthFirstIterator ,
334+ props : Option < VectorOrKeyword < ' e > > ,
335+ output : Option < Vector < ' e > > ,
336+ env : & ' e Env ,
337+ ) -> Result < Value < ' e > > {
318338 let cursor = & iterator. cursor ;
319- let _ = _current_node ( cursor, Some ( props) , Some ( output) , env) ?;
320- for ( i, prop) in props. into_iter ( ) . enumerate ( ) {
321- if prop. eq ( _depth. bind ( env) ) {
322- output. set ( i, iterator. depth ) ?;
339+ match props {
340+ Some ( VectorOrKeyword :: Keyword ( prop) ) if prop. eq ( _depth. bind ( env) ) => {
341+ iterator. depth . into_lisp ( env)
342+ }
343+ _ => {
344+ let result = _current_node ( cursor, props, output, env) ?;
345+ if let Some ( VectorOrKeyword :: Vector ( props) ) = props {
346+ if let Some ( output) = output {
347+ for ( i, prop) in props. into_iter ( ) . enumerate ( ) {
348+ if prop. eq ( _depth. bind ( env) ) {
349+ output. set ( i, iterator. depth ) ?;
350+ }
351+ }
352+ } else {
353+ todo ! ( )
354+ }
355+ }
356+ Ok ( result)
323357 }
324358 }
325- Ok ( ( ) )
326359}
327360
328- /// Move ITERATOR to the next node, and retrieve its properties.
361+ /// Move ITERATOR to the next node, and retrieve its properties, or the node itself .
329362///
330363/// This a combination of `tsc--iter-next' and `tsc--iter-current-node'.
331364#[ defun]
332- fn _iter_next_node ( iterator : & mut DepthFirstIterator , props : Vector , output : Vector ) -> Result < bool > {
365+ fn _iter_next_node < ' e > (
366+ iterator : & mut DepthFirstIterator ,
367+ props : Option < VectorOrKeyword < ' e > > ,
368+ output : Option < Vector < ' e > > ,
369+ env : & ' e Env ,
370+ ) -> Result < Option < Value < ' e > > > {
333371 if iterator. next ( ) . is_some ( ) {
334- _iter_current_node ( iterator, props, output) ?;
335- Ok ( true )
372+ Ok ( Some ( _iter_current_node ( iterator, props, output, env) ?) )
336373 } else {
337- Ok ( false )
374+ Ok ( None )
338375 }
339376}
340377
341- /// Return CURSOR's current node, if PROPS is nil.
342- ///
343- /// If PROPS is a vector of property names, this function returns a vector
344- /// containing the node's corresponding properties instead of the node itself. If
345- /// OUTPUT is also a vector, this function overwrites its contents instead of
346- /// creating a new vector.
347- ///
348- /// See `tsc-valid-node-props' for the list of available properties.
349- #[ defun]
350- fn _current_node < ' e > ( cursor : & RCursor , props : Option < Vector < ' e > > , output : Option < Vector < ' e > > , env : & ' e Env ) -> Result < Value < ' e > > {
378+ fn get < ' e > ( prop : Value < ' e > , node : Node , cursor : & RCursor ) -> Result < Value < ' e > > {
351379 macro_rules! sugar {
352380 ( $prop: ident, $env: ident) => {
353381 macro_rules! eq {
354- ( $name: ident) => ( $prop. eq( $name. bind( $env) ) )
382+ ( $name: ident) => {
383+ $prop. eq( $name. bind( $env) )
384+ } ;
355385 }
356- }
386+ } ;
387+ }
388+ let env = prop. env ;
389+ sugar ! ( prop, env) ;
390+ if eq ! ( _type) {
391+ node. lisp_type ( ) . into_lisp ( env)
392+ } else if eq ! ( _byte_range) {
393+ node. lisp_byte_range ( env)
394+ } else if eq ! ( _start_byte) {
395+ node. lisp_start_byte ( ) . into_lisp ( env)
396+ } else if eq ! ( _end_byte) {
397+ node. lisp_end_byte ( ) . into_lisp ( env)
398+ } else if eq ! ( _field) {
399+ current_field ( cursor) ?. into_lisp ( env)
400+ } else if eq ! ( _named_p) {
401+ node. is_named ( ) . into_lisp ( env)
402+ } else if eq ! ( _extra_p) {
403+ node. is_extra ( ) . into_lisp ( env)
404+ } else if eq ! ( _error_p) {
405+ node. is_error ( ) . into_lisp ( env)
406+ } else if eq ! ( _missing_p) {
407+ node. is_missing ( ) . into_lisp ( env)
408+ } else if eq ! ( _has_error_p) {
409+ node. has_error ( ) . into_lisp ( env)
410+ } else if eq ! ( _start_point) {
411+ node. lisp_start_point ( ) . into_lisp ( env)
412+ } else if eq ! ( _end_point) {
413+ node. lisp_end_point ( ) . into_lisp ( env)
414+ } else if eq ! ( _range) {
415+ node. lisp_range ( ) . into_lisp ( env)
416+ } else {
417+ ( ) . into_lisp ( env)
357418 }
419+ }
420+
421+ /// Return the properties of CURSOR's current node, or the node itself.
422+ ///
423+ /// If PROPS is a vector of property names, return a vector containing the node's
424+ /// corresponding properties. If OUTPUT is also non-nil, it must be a vector of the
425+ /// same length, where the properties will be written into.
426+ ///
427+ /// If PROPS is a single property name, return that property.
428+ ///
429+ /// If PROPS is nil, return the node itself.
430+ ///
431+ /// See `tsc-valid-node-props' for the list of available properties.
432+ #[ defun]
433+ fn _current_node < ' e > (
434+ cursor : & RCursor ,
435+ props : Option < VectorOrKeyword < ' e > > ,
436+ output : Option < Vector < ' e > > ,
437+ env : & ' e Env ,
438+ ) -> Result < Value < ' e > > {
358439 let node = cursor. borrow ( ) . node ( ) ;
359440 match props {
360441 None => RNode :: new ( cursor. clone_tree ( ) , |_| node) . into_lisp ( env) ,
361- Some ( props) => {
442+ Some ( VectorOrKeyword :: Vector ( props) ) => {
362443 let result = match output {
363444 None => env. make_vector ( props. len ( ) , ( ) ) ?,
364445 Some ( output) => output,
365446 } ;
366447 for ( i, prop) in props. into_iter ( ) . enumerate ( ) {
367- sugar ! ( prop, env) ;
368- if eq ! ( _type) {
369- result. set ( i, node. lisp_type ( ) ) ?;
370- } else if eq ! ( _byte_range) {
371- result. set ( i, node. lisp_byte_range ( env) ?) ?;
372- } else if eq ! ( _start_byte) {
373- result. set ( i, node. lisp_start_byte ( ) ) ?;
374- } else if eq ! ( _end_byte) {
375- result. set ( i, node. lisp_end_byte ( ) ) ?;
376- } else if eq ! ( _field) {
377- result. set ( i, current_field ( cursor) ?) ?;
378- } else if eq ! ( _named_p) {
379- result. set ( i, node. is_named ( ) ) ?;
380- } else if eq ! ( _extra_p) {
381- result. set ( i, node. is_extra ( ) ) ?;
382- } else if eq ! ( _error_p) {
383- result. set ( i, node. is_error ( ) ) ?;
384- } else if eq ! ( _missing_p) {
385- result. set ( i, node. is_missing ( ) ) ?;
386- } else if eq ! ( _has_error_p) {
387- result. set ( i, node. has_error ( ) ) ?;
388- } else if eq ! ( _start_point) {
389- result. set ( i, node. lisp_start_point ( ) ) ?;
390- } else if eq ! ( _end_point) {
391- result. set ( i, node. lisp_end_point ( ) ) ?;
392- } else if eq ! ( _range) {
393- result. set ( i, node. lisp_range ( ) ) ?;
394- } else {
395- result. set ( i, ( ) ) ?;
396- }
448+ result. set ( i, get ( prop, node, cursor) ?) ?;
397449 }
398450 result. into_lisp ( env)
399451 }
452+ Some ( VectorOrKeyword :: Keyword ( prop) ) => get ( prop, node, cursor) ,
400453 }
401454}
402455
403456/// Actual logic of `tsc-traverse-mapc'. The wrapper is needed because
404457/// `emacs-module-rs' doesn't currently support optional arguments.
405458#[ defun]
406- fn _traverse_mapc ( func : Value , tree_or_node : TreeOrNode , props : Option < Vector > ) -> Result < ( ) > {
459+ fn _traverse_mapc (
460+ func : Value ,
461+ tree_or_node : TreeOrNode ,
462+ props : Option < VectorOrKeyword > ,
463+ ) -> Result < ( ) > {
407464 let mut iterator = DepthFirstIterator :: new ( tree_or_node) ;
408465 let env = func. env ;
409- let output = match props {
410- None => None ,
411- Some ( props) => Some ( env. make_vector ( props. len ( ) , ( ) ) ?) ,
412- } ;
466+ let mut output = None ;
413467 let mut depth_indexes = Vec :: with_capacity ( 1 ) ;
414- if let Some ( props) = props {
415- for ( i, prop) in props. into_iter ( ) . enumerate ( ) {
416- if prop. eq ( _depth. bind ( env) ) {
417- depth_indexes. push ( i)
468+ let mut depth = false ;
469+ match props {
470+ Some ( VectorOrKeyword :: Vector ( props) ) => {
471+ output = Some ( env. make_vector ( props. len ( ) , ( ) ) ?) ;
472+ for ( i, prop) in props. into_iter ( ) . enumerate ( ) {
473+ if prop. eq ( _depth. bind ( env) ) {
474+ depth_indexes. push ( i)
475+ }
418476 }
419477 }
478+ Some ( VectorOrKeyword :: Keyword ( prop) ) if prop. eq ( _depth. bind ( env) ) => {
479+ depth = true ;
480+ }
481+ _ => { }
420482 }
421483 // Can't use a for loop because we need to access the cursor to process each item.
422484 let mut item: Option < ( RNode , usize ) > = iterator. next ( ) ;
423485 while item. is_some ( ) {
424- let result = _current_node ( & iterator. cursor , props, output, env) ?;
425- // let (_, depth) = item.unwrap();
426-
427- if let Some ( output) = output {
428- for i in & depth_indexes {
429- output. set ( * i, iterator. depth ) ?;
486+ let result = if depth {
487+ iterator. depth . into_lisp ( env) ?
488+ } else {
489+ let result = _current_node ( & iterator. cursor , props, output, env) ?;
490+ if let Some ( output) = output {
491+ for i in & depth_indexes {
492+ output. set ( * i, iterator. depth ) ?;
493+ }
430494 }
431- }
495+ result
496+ } ;
432497
433498 // Safety: the returned value is unused.
434- unsafe { func. call_unprotected ( [ result] ) ?; }
499+ unsafe {
500+ func. call_unprotected ( [ result] ) ?;
501+ }
435502
436503 // // Safety: the returned value is unused.
437504 // unsafe { func.call_unprotected((result, depth))?; }
0 commit comments