vimlrs 0.2.1

Faithful Rust port of the Vimscript (VimL) interpreter, from the Neovim C eval engine
Documentation
vim9script
# vim9_var_assign.vim — vim9script variable declaration and assignment:
#   • a type-only `var x: T` declaration (no initializer) default-inits to T's
#     zero value (`:help vim9-declaration`);
#   • a bare `x = expr` / `x += expr` / `x ..= expr` reassignment (no `:let`/
#     `:var` keyword), the vim9 way of assigning to a declared variable.
#
# Everything below is real vim9script, binary-verified against Vim 9.2. Types
# are parsed and ignored (the type system is deferred); the runtime values are
# what the assertions pin. Self-tests into v:errors.
#
#   vimlrs examples/vim9_var_assign.vim

# ── type-only declaration → per-type zero value (string '', number 0, list [],
#    dict {}, bool false, float 0.0) ──
def Defaults(): list<any>
  var s: string
  var n: number
  var l: list<number>
  var d: dict<number>
  var b: bool
  var f: float
  return [s, n, l, d, b, f]
enddef
var r = Defaults()
assert_equal('', r[0])
assert_equal(0, r[1])
assert_equal([], r[2])
assert_equal({}, r[3])
assert_equal(false, r[4])
assert_equal(0.0, r[5])

# ── bare reassignment: compound arithmetic (`+=`, `*=`), string append (`..=`),
#    indexed dict assign, and method-call mutation of a default-init list ──
def Reassign(): list<any>
  var n = 5
  n += 3
  n *= 2
  var s = 'a'
  s ..= 'b'
  s ..= 'c'
  var d: dict<number>
  d['k'] = 9
  var lst: list<number>
  lst->add(1)
  lst->add(2)
  return [n, s, d, lst]
enddef
var q = Reassign()
assert_equal(16, q[0])
assert_equal('abc', q[1])
assert_equal({'k': 9}, q[2])
assert_equal([1, 2], q[3])

# ── top-level bare reassignment (outside any def) ──
var top = 10
top -= 4
assert_equal(6, top)

# ── a CamelCase script variable assigns (must not be read as a user command) ──
var Total = 0
Total += 7
assert_equal(7, Total)

# ── bare list-unpack assignment `[a, b] = expr` (no `var`/`:let` keyword): the
#    vim9 way to reassign several already-declared names at once. Distinct from
#    the `var [a, b] = …` declaration form; binary-verified against Vim 9.2. ──
var ua = 0
var ub = 0
[ua, ub] = [1, 2]
assert_equal(1, ua)
assert_equal(2, ub)

# swap: the rhs is fully built before any target is bound
[ua, ub] = [ub, ua]
assert_equal([2, 1], [ua, ub])

# `[a, b; rest]`: the trailing name soaks up the remainder as a list
var uh = 0
var ut = 0
var urest: list<number> = []
[uh, ut; urest] = [10, 20, 30, 40]
assert_equal(10, uh)
assert_equal(20, ut)
assert_equal([30, 40], urest)

# a rest binding matches exactly zero remaining elements
[uh; urest] = [99]
assert_equal(99, uh)
assert_equal([], urest)

# unpack assignment inside a def, targeting locals
def UnpackLocal(): number
  var x = 0
  var y = 0
  [x, y] = [3, 4]
  return x + y
enddef
assert_equal(7, UnpackLocal())

# ── self-test epilogue ──
if !empty(v:errors)
  for e in v:errors
    echo 'FAIL:' e
  endfor
  throw len(v:errors) .. ' assertion(s) failed'
endif