@@ -1913,20 +1913,43 @@ define_builtin!(
19131913 . unwrap_or( RuntimeValue :: NONE ) ) ,
19141914 [ RuntimeValue :: Dict ( map) , RuntimeValue :: Symbol ( key) ] =>
19151915 Ok ( map. get_mut( key) . map( std:: mem:: take) . unwrap_or( RuntimeValue :: NONE ) ) ,
1916- [ RuntimeValue :: Array ( array) , RuntimeValue :: Number ( index) ] => Ok ( array
1917- . get_mut( index. value( ) as usize )
1918- . map( std:: mem:: take)
1919- . unwrap_or( RuntimeValue :: NONE ) ) ,
1916+ [ RuntimeValue :: Array ( array) , RuntimeValue :: Number ( index) ] => {
1917+ let len = array. len( ) ;
1918+ let idx = index. value( ) as isize ;
1919+ let real_idx = if idx < 0 {
1920+ ( len as isize + idx) . max( 0 ) as usize
1921+ } else {
1922+ idx as usize
1923+ } ;
1924+ Ok ( array
1925+ . get_mut( real_idx)
1926+ . map( std:: mem:: take)
1927+ . unwrap_or( RuntimeValue :: NONE ) )
1928+ }
19201929 [ RuntimeValue :: String ( s) , RuntimeValue :: Number ( n) ] => {
1921- match s. chars( ) . nth( n. value( ) as usize ) {
1930+ let len = s. chars( ) . count( ) ;
1931+ let idx = n. value( ) as isize ;
1932+ let real_idx = if idx < 0 {
1933+ ( len as isize + idx) . max( 0 ) as usize
1934+ } else {
1935+ idx as usize
1936+ } ;
1937+ match s. chars( ) . nth( real_idx) {
19221938 Some ( o) => Ok ( o. to_string( ) . into( ) ) ,
19231939 None => Ok ( RuntimeValue :: NONE ) ,
19241940 }
19251941 }
19261942 [ RuntimeValue :: Markdown ( node, _) , RuntimeValue :: Number ( i) ] => {
1943+ let idx = i. value( ) as isize ;
1944+ let real_idx = if idx < 0 {
1945+ let len = node. value( ) . chars( ) . count( ) ;
1946+ ( len as isize + idx) . max( 0 ) as usize
1947+ } else {
1948+ idx as usize
1949+ } ;
19271950 Ok ( RuntimeValue :: Markdown (
19281951 std:: mem:: replace( node, mq_markdown:: Node :: Empty ) ,
1929- Some ( runtime_value:: Selector :: Index ( i . value ( ) as usize ) ) ,
1952+ Some ( runtime_value:: Selector :: Index ( real_idx ) ) ,
19301953 ) )
19311954 }
19321955 [ RuntimeValue :: None , _] | [ _, RuntimeValue :: None ] => Ok ( RuntimeValue :: NONE ) ,
0 commit comments