vimlrs 0.2.1

Faithful Rust port of the Vimscript (VimL) interpreter, from the Neovim C eval engine
Documentation
" dot_operator.vim — the '.' operator's runtime subscript-vs-concat dispatch.
"
" A no-space `base.name` is syntactically identical whether it is a Dict
" subscript (`d.key`) or string concatenation (`a.b` with two string vars).
" Vim decides by the RUNTIME type of `base`: a Dict → member subscript, anything
" else → `.`-concatenation (the RHS `name` is a bare variable read). vimlrs lowers
" this to a bytecode type test that dispatches at execution time, single-evaluating
" `base` so side effects fire once and chains like `a.b.c` do not blow up.
"
"   vimlrs examples/dot_operator.vim

" --- concat: literals, numbers, and STRING VARIABLES (the runtime-dispatch case)
call assert_equal('ab', 'a'.'b')
call assert_equal('12', 1 . 2)
let a = 'p'
let b = 'q'
call assert_equal('pq', a.b)

" --- concat chains: every '.' concatenates when the bases are strings
let c = 'r'
call assert_equal('pqr', a.b.c)

" --- Dict subscript: the same syntax reads a member when base is a Dict
let d = {'x': 5, 'f': 1, 'g': 2}
call assert_equal(5, d.x)
call assert_equal(3, d.f + d.g)
let nested = {'a': {'b': 7}}
call assert_equal(7, nested.a.b)

" --- Dict subscript then a spaced concat, and a subscript on the member result
call assert_equal('5z', d.x . 'z')
let lists = {'x': [10, 20]}
call assert_equal(20, lists.x[1])

" --- a member value used inside a concatenation
let who = {'name': 'fox'}
call assert_equal('hi fox', 'hi ' . who.name)

" --- lambda-body concat: `a.b` over the lambda params, folded by reduce()
call assert_equal('abc', reduce(['a', 'b', 'c'], {x, y -> x.y}, ''))

" --- base is evaluated exactly once for both branches (no double-eval).
let g:calls = 0
function! Dictbase() abort
  let g:calls += 1
  return {'x': 42}
endfunction
call assert_equal(42, Dictbase().x)
call assert_equal(1, g:calls)

let g:calls = 0
function! Strbase() abort
  let g:calls += 1
  return 'p'
endfunction
let tail = 'q'
call assert_equal('pq', Strbase().tail)
call assert_equal(1, g:calls)

" --- self-test epilogue ---
if len(v:errors) > 0
  for err in v:errors
    echo 'FAIL:' err
  endfor
  throw 'dot_operator.vim: ' . len(v:errors) . ' assertion(s) failed'
endif
echo 'dot_operator.vim: all assertions passed'