mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.1744: Vim9: using ":const!" is weird
Problem: Vim9: using ":const!" is weird. Solution: Use "var" - "final" - "const" like Dart. "let" still works for now.
This commit is contained in:
parent
273af497ca
commit
30fd8204ce
@ -1,4 +1,4 @@
|
|||||||
*vim9.txt* For Vim version 8.2. Last change: 2020 Sep 17
|
*vim9.txt* For Vim version 8.2. Last change: 2020 Sep 26
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@ -70,7 +70,7 @@ Comments starting with # ~
|
|||||||
In legacy Vim script comments start with double quote. In Vim9 script
|
In legacy Vim script comments start with double quote. In Vim9 script
|
||||||
comments start with #. >
|
comments start with #. >
|
||||||
# declarations
|
# declarations
|
||||||
let count = 0 # number of occurrences
|
var count = 0 # number of occurrences
|
||||||
|
|
||||||
The reason is that a double quote can also be the start of a string. In many
|
The reason is that a double quote can also be the start of a string. In many
|
||||||
places, especially halfway through an expression with a line break, it's hard
|
places, especially halfway through an expression with a line break, it's hard
|
||||||
@ -154,31 +154,32 @@ Vim9 script script-local functions are defined once when the script is sourced
|
|||||||
and cannot be deleted or replaced.
|
and cannot be deleted or replaced.
|
||||||
|
|
||||||
|
|
||||||
Variable declarations with :let and :const ~
|
Variable declarations with :var, :final and :const ~
|
||||||
*vim9-declaration*
|
*vim9-declaration*
|
||||||
Local variables need to be declared with `:let`. Local constants need to be
|
Local variables need to be declared with `:var`. Local constants need to be
|
||||||
declared with `:const`. We refer to both as "variables".
|
declared with `:final` or `:const`. We refer to both as "variables" in this
|
||||||
|
section.
|
||||||
|
|
||||||
Variables can be local to a script, function or code block: >
|
Variables can be local to a script, function or code block: >
|
||||||
vim9script
|
vim9script
|
||||||
let script_var = 123
|
var script_var = 123
|
||||||
def SomeFunc()
|
def SomeFunc()
|
||||||
let func_var = script_var
|
var func_var = script_var
|
||||||
if cond
|
if cond
|
||||||
let block_var = func_var
|
var block_var = func_var
|
||||||
...
|
...
|
||||||
|
|
||||||
The variables are only visible in the block where they are defined and nested
|
The variables are only visible in the block where they are defined and nested
|
||||||
blocks. Once the block ends the variable is no longer accessible: >
|
blocks. Once the block ends the variable is no longer accessible: >
|
||||||
if cond
|
if cond
|
||||||
let inner = 5
|
var inner = 5
|
||||||
else
|
else
|
||||||
let inner = 0
|
var inner = 0
|
||||||
endif
|
endif
|
||||||
echo inner # Error!
|
echo inner # Error!
|
||||||
|
|
||||||
The declaration must be done earlier: >
|
The declaration must be done earlier: >
|
||||||
let inner: number
|
var inner: number
|
||||||
if cond
|
if cond
|
||||||
inner = 5
|
inner = 5
|
||||||
else
|
else
|
||||||
@ -186,10 +187,10 @@ The declaration must be done earlier: >
|
|||||||
endif
|
endif
|
||||||
echo inner
|
echo inner
|
||||||
|
|
||||||
To intentionally avoid a variable being available later, a block can be used:
|
To intentionally hide a variable from code that follows, a block can be
|
||||||
>
|
used: >
|
||||||
{
|
{
|
||||||
let temp = 'temp'
|
var temp = 'temp'
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
echo temp # Error!
|
echo temp # Error!
|
||||||
@ -197,9 +198,9 @@ To intentionally avoid a variable being available later, a block can be used:
|
|||||||
Declaring a variable with a type but without an initializer will initialize to
|
Declaring a variable with a type but without an initializer will initialize to
|
||||||
zero, false or empty.
|
zero, false or empty.
|
||||||
|
|
||||||
An existing variable cannot be assigned to with `:let`, since that implies a
|
In Vim9 script `:let` cannot be used. An existing variable is assigned to
|
||||||
declaration. Global, window, tab, buffer and Vim variables can only be used
|
without any command. The same for global, window, tab, buffer and Vim
|
||||||
without `:let`, because they are not really declared, they can also be deleted
|
variables, because they are not really declared. They can also be deleted
|
||||||
with `:unlet`.
|
with `:unlet`.
|
||||||
|
|
||||||
Variables and functions cannot shadow previously defined or imported variables
|
Variables and functions cannot shadow previously defined or imported variables
|
||||||
@ -209,51 +210,50 @@ Variables may shadow Ex commands, rename the variable if needed.
|
|||||||
Global variables and user defined functions must be prefixed with "g:", also
|
Global variables and user defined functions must be prefixed with "g:", also
|
||||||
at the script level. >
|
at the script level. >
|
||||||
vim9script
|
vim9script
|
||||||
let script_local = 'text'
|
var script_local = 'text'
|
||||||
g:global = 'value'
|
g:global = 'value'
|
||||||
let Funcref = g:ThatFunction
|
var Funcref = g:ThatFunction
|
||||||
|
|
||||||
Since "&opt = value" is now assigning a value to option "opt", ":&" cannot be
|
Since `&opt = value` is now assigning a value to option "opt", ":&" cannot be
|
||||||
used to repeat a `:substitute` command.
|
used to repeat a `:substitute` command.
|
||||||
*vim9-const*
|
|
||||||
In legacy Vim script "const list = []" would make the variable "list"
|
|
||||||
immutable and also the value. Thus you cannot add items to the list. This
|
|
||||||
differs from what many languages do. Vim9 script does it like TypeScript: only
|
|
||||||
"list" is immutable, the value can be changed.
|
|
||||||
|
|
||||||
One can use `:const!` to make both the variable and the value immutable. Use
|
|
||||||
|
Constants ~
|
||||||
|
*vim9-const* *vim9-final*
|
||||||
|
How constants work varies between languages. Some consider a variable that
|
||||||
|
can't be assigned another value a constant. JavaScript is an example. Others
|
||||||
|
also make the value immutable, thus when a constant uses a list, the list
|
||||||
|
cannot be changed. In Vim9 we can use both.
|
||||||
|
|
||||||
|
`:const` is used for making both the variable and the value a constant. Use
|
||||||
this for composite structures that you want to make sure will not be modified.
|
this for composite structures that you want to make sure will not be modified.
|
||||||
|
Example: >
|
||||||
|
const myList = [1, 2]
|
||||||
|
myList = [3, 4] # Error!
|
||||||
|
myList[0] = 9 # Error!
|
||||||
|
muList->add(3) # Error!
|
||||||
|
|
||||||
How this works: >
|
`:final` is used for making only the variable a constant, the value can be
|
||||||
vim9script
|
changed. This is well known from Java. Example: >
|
||||||
const list = [1, 2]
|
final myList = [1, 2]
|
||||||
list = [3, 4] # Error!
|
myList = [3, 4] # Error!
|
||||||
list[0] = 2 # OK
|
myList[0] = 9 # OK
|
||||||
|
muList->add(3) # OK
|
||||||
|
|
||||||
const! LIST = [1, 2]
|
|
||||||
LIST = [3, 4] # Error!
|
|
||||||
LIST[0] = 2 # Error!
|
|
||||||
It is common to write constants as ALL_CAPS, but you don't have to.
|
It is common to write constants as ALL_CAPS, but you don't have to.
|
||||||
|
|
||||||
The constant only applies to the value itself, not what it refers to. >
|
The constant only applies to the value itself, not what it refers to. >
|
||||||
cont females = ["Mary"]
|
final females = ["Mary"]
|
||||||
const! NAMES = [["John", "Peter"], females]
|
const NAMES = [["John", "Peter"], females]
|
||||||
NAMES[0] = ["Jack"] # Error!
|
NAMES[0] = ["Jack"] # Error!
|
||||||
NAMES[0][0] = ["Jack"] # Error!
|
NAMES[0][0] = "Jack" # Error!
|
||||||
NAMES[1] = ["Emma"] # Error!
|
NAMES[1] = ["Emma"] # Error!
|
||||||
Names[1][0] = "Emma" # OK, now females[0] == "Emma"
|
Names[1][0] = "Emma" # OK, now females[0] == "Emma"
|
||||||
|
|
||||||
Rationale: TypeScript has no way to make the value immutable. One can use
|
< *E1092*
|
||||||
immutable types, but that quickly gets complicated for nested values. And
|
|
||||||
with a type cast the value can be made mutable again, which means there is no
|
|
||||||
guarantee the value won't change. Vim supports immutable values, in legacy
|
|
||||||
script this was done with `:lockvar`. But that is an extra statement and also
|
|
||||||
applies to nested values. Therefore the solution to use `:const!`.
|
|
||||||
|
|
||||||
*E1092*
|
|
||||||
Declaring more than one variable at a time, using the unpack notation, is
|
Declaring more than one variable at a time, using the unpack notation, is
|
||||||
currently not supported: >
|
currently not supported: >
|
||||||
let [v1, v2] = GetValues() # Error!
|
var [v1, v2] = GetValues() # Error!
|
||||||
That is because the type needs to be inferred from the list item type, which
|
That is because the type needs to be inferred from the list item type, which
|
||||||
isn't that easy.
|
isn't that easy.
|
||||||
|
|
||||||
@ -296,7 +296,7 @@ A user defined function can be used as a function reference in an expression
|
|||||||
without `function()`. The argument types and return type will then be checked.
|
without `function()`. The argument types and return type will then be checked.
|
||||||
The function must already have been defined. >
|
The function must already have been defined. >
|
||||||
|
|
||||||
let Funcref = MyFunction
|
var Funcref = MyFunction
|
||||||
|
|
||||||
When using `function()` the resulting type is "func", a function with any
|
When using `function()` the resulting type is "func", a function with any
|
||||||
number of arguments and any return type. The function can be defined later.
|
number of arguments and any return type. The function can be defined later.
|
||||||
@ -307,53 +307,53 @@ Automatic line continuation ~
|
|||||||
In many cases it is obvious that an expression continues on the next line. In
|
In many cases it is obvious that an expression continues on the next line. In
|
||||||
those cases there is no need to prefix the line with a backslash
|
those cases there is no need to prefix the line with a backslash
|
||||||
|line-continuation|. For example, when a list spans multiple lines: >
|
|line-continuation|. For example, when a list spans multiple lines: >
|
||||||
let mylist = [
|
var mylist = [
|
||||||
'one',
|
'one',
|
||||||
'two',
|
'two',
|
||||||
]
|
]
|
||||||
And when a dict spans multiple lines: >
|
And when a dict spans multiple lines: >
|
||||||
let mydict = #{
|
var mydict = #{
|
||||||
one: 1,
|
one: 1,
|
||||||
two: 2,
|
two: 2,
|
||||||
}
|
}
|
||||||
Function call: >
|
Function call: >
|
||||||
let result = Func(
|
var result = Func(
|
||||||
arg1,
|
arg1,
|
||||||
arg2
|
arg2
|
||||||
)
|
)
|
||||||
|
|
||||||
For binary operators in expressions not in [], {} or () a line break is
|
For binary operators in expressions not in [], {} or () a line break is
|
||||||
possible just before or after the operator. For example: >
|
possible just before or after the operator. For example: >
|
||||||
let text = lead
|
var text = lead
|
||||||
.. middle
|
.. middle
|
||||||
.. end
|
.. end
|
||||||
let total = start +
|
var total = start +
|
||||||
end -
|
end -
|
||||||
correction
|
correction
|
||||||
let result = positive
|
var result = positive
|
||||||
? PosFunc(arg)
|
? PosFunc(arg)
|
||||||
: NegFunc(arg)
|
: NegFunc(arg)
|
||||||
|
|
||||||
For a method call using "->" and a member using a dot, a line break is allowed
|
For a method call using "->" and a member using a dot, a line break is allowed
|
||||||
before it: >
|
before it: >
|
||||||
let result = GetBuilder()
|
var result = GetBuilder()
|
||||||
->BuilderSetWidth(333)
|
->BuilderSetWidth(333)
|
||||||
->BuilderSetHeight(777)
|
->BuilderSetHeight(777)
|
||||||
->BuilderBuild()
|
->BuilderBuild()
|
||||||
let result = MyDict
|
var result = MyDict
|
||||||
.member
|
.member
|
||||||
|
|
||||||
< *E1050*
|
< *E1050*
|
||||||
To make it possible for the operator at the start of the line to be
|
To make it possible for the operator at the start of the line to be
|
||||||
recognized, it is required to put a colon before a range. This will add
|
recognized, it is required to put a colon before a range. This will add
|
||||||
"start" and print: >
|
"start" and print: >
|
||||||
let result = start
|
var result = start
|
||||||
+ print
|
+ print
|
||||||
Like this: >
|
Like this: >
|
||||||
let result = start + print
|
var result = start + print
|
||||||
|
|
||||||
This will assign "start" and print a line: >
|
This will assign "start" and print a line: >
|
||||||
let result = start
|
var result = start
|
||||||
:+ print
|
:+ print
|
||||||
|
|
||||||
It is also possible to split a function header over multiple lines, in between
|
It is also possible to split a function header over multiple lines, in between
|
||||||
@ -411,15 +411,15 @@ The 'ignorecase' option is not used for comparators that use strings.
|
|||||||
White space ~
|
White space ~
|
||||||
|
|
||||||
Vim9 script enforces proper use of white space. This is no longer allowed: >
|
Vim9 script enforces proper use of white space. This is no longer allowed: >
|
||||||
let var=234 # Error!
|
var name=234 # Error!
|
||||||
let var= 234 # Error!
|
var name= 234 # Error!
|
||||||
let var =234 # Error!
|
var name =234 # Error!
|
||||||
There must be white space before and after the "=": >
|
There must be white space before and after the "=": >
|
||||||
let var = 234 # OK
|
var name = 234 # OK
|
||||||
White space must also be put before the # that starts a comment after a
|
White space must also be put before the # that starts a comment after a
|
||||||
command: >
|
command: >
|
||||||
let var = 234# Error!
|
var name = 234# Error!
|
||||||
let var = 234 # OK
|
var name = 234 # OK
|
||||||
|
|
||||||
White space is required around most operators.
|
White space is required around most operators.
|
||||||
|
|
||||||
@ -440,7 +440,7 @@ Conditions and expressions ~
|
|||||||
|
|
||||||
Conditions and expressions are mostly working like they do in JavaScript. A
|
Conditions and expressions are mostly working like they do in JavaScript. A
|
||||||
difference is made where JavaScript does not work like most people expect.
|
difference is made where JavaScript does not work like most people expect.
|
||||||
Specifically, an empty list is falsey.
|
Specifically, an empty list is falsy.
|
||||||
|
|
||||||
Any type of variable can be used as a condition, there is no error, not even
|
Any type of variable can be used as a condition, there is no error, not even
|
||||||
for using a list or job. This is very much like JavaScript, but there are a
|
for using a list or job. This is very much like JavaScript, but there are a
|
||||||
@ -582,9 +582,10 @@ THIS IS STILL UNDER DEVELOPMENT - ANYTHING CAN BREAK - ANYTHING CAN CHANGE
|
|||||||
It is possible to nest `:def` inside another `:def` or
|
It is possible to nest `:def` inside another `:def` or
|
||||||
`:function` up to about 50 levels deep.
|
`:function` up to about 50 levels deep.
|
||||||
|
|
||||||
[!] is used as with `:function`. Note that in Vim9
|
[!] is used as with `:function`. Note that
|
||||||
script script-local functions cannot be deleted or
|
script-local functions cannot be deleted or redefined
|
||||||
redefined later in the same script.
|
later in Vim9 script. They can only be removed by
|
||||||
|
reloading the same script.
|
||||||
|
|
||||||
*:enddef*
|
*:enddef*
|
||||||
:enddef End of a function defined with `:def`. It should be on
|
:enddef End of a function defined with `:def`. It should be on
|
||||||
@ -612,14 +613,14 @@ Limitations ~
|
|||||||
|
|
||||||
Local variables will not be visible to string evaluation. For example: >
|
Local variables will not be visible to string evaluation. For example: >
|
||||||
def EvalString(): list<string>
|
def EvalString(): list<string>
|
||||||
let list = ['aa', 'bb', 'cc', 'dd']
|
var list = ['aa', 'bb', 'cc', 'dd']
|
||||||
return range(1, 2)->map('list[v:val]')
|
return range(1, 2)->map('list[v:val]')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
The map argument is a string expression, which is evaluated without the
|
The map argument is a string expression, which is evaluated without the
|
||||||
function scope. Instead, use a lambda: >
|
function scope. Instead, use a lambda: >
|
||||||
def EvalString(): list<string>
|
def EvalString(): list<string>
|
||||||
let list = ['aa', 'bb', 'cc', 'dd']
|
var list = ['aa', 'bb', 'cc', 'dd']
|
||||||
return range(1, 2)->map({ _, v -> list[v] })
|
return range(1, 2)->map({ _, v -> list[v] })
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
@ -690,23 +691,23 @@ builtin types added later, similarly to user functions.
|
|||||||
|
|
||||||
And classes and interfaces can be used as types: >
|
And classes and interfaces can be used as types: >
|
||||||
:class MyClass
|
:class MyClass
|
||||||
:let mine: MyClass
|
:var mine: MyClass
|
||||||
|
|
||||||
:interface MyInterface
|
:interface MyInterface
|
||||||
:let mine: MyInterface
|
:var mine: MyInterface
|
||||||
|
|
||||||
:class MyTemplate<Targ>
|
:class MyTemplate<Targ>
|
||||||
:let mine: MyTemplate<number>
|
:var mine: MyTemplate<number>
|
||||||
:let mine: MyTemplate<string>
|
:var mine: MyTemplate<string>
|
||||||
|
|
||||||
:class MyInterface<Targ>
|
:class MyInterface<Targ>
|
||||||
:let mine: MyInterface<number>
|
:var mine: MyInterface<number>
|
||||||
:let mine: MyInterface<string>
|
:var mine: MyInterface<string>
|
||||||
{not implemented yet}
|
{not implemented yet}
|
||||||
|
|
||||||
|
|
||||||
Variable types and type casting *variable-types*
|
Variable types and type casting ~
|
||||||
|
*variable-types*
|
||||||
Variables declared in Vim9 script or in a `:def` function have a type, either
|
Variables declared in Vim9 script or in a `:def` function have a type, either
|
||||||
specified explicitly or inferred from the initialization.
|
specified explicitly or inferred from the initialization.
|
||||||
|
|
||||||
@ -716,10 +717,10 @@ compiled code the "any" type is assumed.
|
|||||||
|
|
||||||
This can be a problem when the "any" type is undesired and the actual type is
|
This can be a problem when the "any" type is undesired and the actual type is
|
||||||
expected to always be the same. For example, when declaring a list: >
|
expected to always be the same. For example, when declaring a list: >
|
||||||
let l: list<number> = [1, g:two]
|
var l: list<number> = [1, g:two]
|
||||||
This will give an error, because "g:two" has type "any". To avoid this, use a
|
This will give an error, because "g:two" has type "any". To avoid this, use a
|
||||||
type cast: >
|
type cast: >
|
||||||
let l: list<number> = [1, <number>g:two]
|
var l: list<number> = [1, <number>g:two]
|
||||||
< *type-casting*
|
< *type-casting*
|
||||||
The compiled code will then check that "g:two" is a number at runtime and give
|
The compiled code will then check that "g:two" is a number at runtime and give
|
||||||
an error if it isn't. This is called type casting.
|
an error if it isn't. This is called type casting.
|
||||||
@ -734,12 +735,12 @@ it to a string, use the |string()| function. Or use |str2nr()| to convert a
|
|||||||
string to a number.
|
string to a number.
|
||||||
|
|
||||||
|
|
||||||
Type inference *type-inference*
|
Type inference ~
|
||||||
|
*type-inference*
|
||||||
In general: Whenever the type is clear it can be omitted. For example, when
|
In general: Whenever the type is clear it can be omitted. For example, when
|
||||||
declaring a variable and giving it a value: >
|
declaring a variable and giving it a value: >
|
||||||
let var = 0 # infers number type
|
var name = 0 # infers number type
|
||||||
let var = 'hello' # infers string type
|
var name = 'hello' # infers string type
|
||||||
|
|
||||||
The type of a list and dictionary comes from the common type of the values.
|
The type of a list and dictionary comes from the common type of the values.
|
||||||
If the values all have the same type, that type is used for the list or
|
If the values all have the same type, that type is used for the list or
|
||||||
@ -749,8 +750,8 @@ dictionary. If there is a mix of types, the "any" type is used. >
|
|||||||
[1, 'x', 3] list<any>
|
[1, 'x', 3] list<any>
|
||||||
|
|
||||||
|
|
||||||
Stricter type checking *type-checking*
|
Stricter type checking ~
|
||||||
|
*type-checking*
|
||||||
In legacy Vim script, where a number was expected, a string would be
|
In legacy Vim script, where a number was expected, a string would be
|
||||||
automatically converted to a number. This was convenient for an actual number
|
automatically converted to a number. This was convenient for an actual number
|
||||||
such as "123", but leads to unexpected problems (but no error message) if the
|
such as "123", but leads to unexpected problems (but no error message) if the
|
||||||
@ -786,7 +787,7 @@ appear as the first statement in the file. It tells Vim to interpret the
|
|||||||
script in its own namespace, instead of the global namespace. If a file
|
script in its own namespace, instead of the global namespace. If a file
|
||||||
starts with: >
|
starts with: >
|
||||||
vim9script
|
vim9script
|
||||||
let myvar = 'yes'
|
var myvar = 'yes'
|
||||||
Then "myvar" will only exist in this file. While without `vim9script` it would
|
Then "myvar" will only exist in this file. While without `vim9script` it would
|
||||||
be available as `g:myvar` from any other script and function.
|
be available as `g:myvar` from any other script and function.
|
||||||
|
|
||||||
@ -809,7 +810,9 @@ Export ~
|
|||||||
*:export* *:exp*
|
*:export* *:exp*
|
||||||
Exporting an item can be written as: >
|
Exporting an item can be written as: >
|
||||||
export const EXPORTED_CONST = 1234
|
export const EXPORTED_CONST = 1234
|
||||||
export let someValue = ...
|
export var someValue = ...
|
||||||
|
export final someValue = ...
|
||||||
|
export const someValue = ...
|
||||||
export def MyFunc() ...
|
export def MyFunc() ...
|
||||||
export class MyClass ...
|
export class MyClass ...
|
||||||
|
|
||||||
@ -880,7 +883,7 @@ actually needed. A recommended mechanism:
|
|||||||
vim9script
|
vim9script
|
||||||
import FilterFunc from "../import/someother.vim"
|
import FilterFunc from "../import/someother.vim"
|
||||||
def searchfor#Stuff(arg: string)
|
def searchfor#Stuff(arg: string)
|
||||||
let filtered = FilterFunc(arg)
|
var filtered = FilterFunc(arg)
|
||||||
...
|
...
|
||||||
< This goes in .../autoload/searchfor.vim. "searchfor" in the file name
|
< This goes in .../autoload/searchfor.vim. "searchfor" in the file name
|
||||||
must be exactly the same as the prefix for the function name, that is how
|
must be exactly the same as the prefix for the function name, that is how
|
||||||
@ -889,7 +892,7 @@ actually needed. A recommended mechanism:
|
|||||||
3. Other functionality, possibly shared between plugins, contains the exported
|
3. Other functionality, possibly shared between plugins, contains the exported
|
||||||
items and any private items. >
|
items and any private items. >
|
||||||
vim9script
|
vim9script
|
||||||
let localVar = 'local'
|
var localVar = 'local'
|
||||||
export def FilterFunc(arg: string): string
|
export def FilterFunc(arg: string): string
|
||||||
...
|
...
|
||||||
< This goes in .../import/someother.vim.
|
< This goes in .../import/someother.vim.
|
||||||
@ -909,7 +912,7 @@ namespace will be used for the imported item, even when "s:" is not specified.
|
|||||||
6. Future work: classes *vim9-classes*
|
6. Future work: classes *vim9-classes*
|
||||||
|
|
||||||
Above "class" was mentioned a few times, but it has not been implemented yet.
|
Above "class" was mentioned a few times, but it has not been implemented yet.
|
||||||
Most of Vim9 script can be created without this funcionality, and since
|
Most of Vim9 script can be created without this functionality, and since
|
||||||
implementing classes is going to be a lot of work, it is left for the future.
|
implementing classes is going to be a lot of work, it is left for the future.
|
||||||
For now we'll just make sure classes can be added later.
|
For now we'll just make sure classes can be added later.
|
||||||
|
|
||||||
@ -941,7 +944,7 @@ invoke callbacks and handle timeouts and errors.
|
|||||||
|
|
||||||
The :def command ~
|
The :def command ~
|
||||||
|
|
||||||
Plugin writers have asked for a much faster Vim script. Investigations have
|
Plugin writers have asked for much faster Vim script. Investigations have
|
||||||
shown that keeping the existing semantics of function calls make this close to
|
shown that keeping the existing semantics of function calls make this close to
|
||||||
impossible, because of the overhead involved with calling a function, setting
|
impossible, because of the overhead involved with calling a function, setting
|
||||||
up the local function scope and executing lines. There are many details that
|
up the local function scope and executing lines. There are many details that
|
||||||
@ -952,7 +955,7 @@ much overhead that cannot be avoided.
|
|||||||
Therefore the `:def` method to define a new-style function had to be added,
|
Therefore the `:def` method to define a new-style function had to be added,
|
||||||
which allows for a function with different semantics. Most things still work
|
which allows for a function with different semantics. Most things still work
|
||||||
as before, but some parts do not. A new way to define a function was
|
as before, but some parts do not. A new way to define a function was
|
||||||
considered the best way to separate the old-style code from Vim9 script code.
|
considered the best way to separate the legacy style code from Vim9 style code.
|
||||||
|
|
||||||
Using "def" to define a function comes from Python. Other languages use
|
Using "def" to define a function comes from Python. Other languages use
|
||||||
"function" which clashes with legacy Vim script.
|
"function" which clashes with legacy Vim script.
|
||||||
@ -968,12 +971,12 @@ instruction, at execution time the instruction would have to inspect the type
|
|||||||
of the arguments and decide what kind of addition to do. And when the
|
of the arguments and decide what kind of addition to do. And when the
|
||||||
type is dictionary throw an error. If the types are known to be numbers then
|
type is dictionary throw an error. If the types are known to be numbers then
|
||||||
an "add number" instruction can be used, which is faster. The error can be
|
an "add number" instruction can be used, which is faster. The error can be
|
||||||
given at compile time, no error handling is needed at runtime, adding two
|
given at compile time, no error handling is needed at runtime, since adding
|
||||||
numbers cannot fail.
|
two numbers cannot fail.
|
||||||
|
|
||||||
The syntax for types is similar to Java, since it is easy to understand and
|
The syntax for types, using <type> for compound types, is similar to Java. It
|
||||||
widely used. The type names are what were used in Vim before, with some
|
is easy to understand and widely used. The type names are what were used in
|
||||||
additions such as "void" and "bool".
|
Vim before, with some additions such as "void" and "bool".
|
||||||
|
|
||||||
|
|
||||||
Removing clutter and weirdness ~
|
Removing clutter and weirdness ~
|
||||||
@ -981,10 +984,10 @@ Removing clutter and weirdness ~
|
|||||||
Once decided that `:def` functions have different syntax than legacy functions,
|
Once decided that `:def` functions have different syntax than legacy functions,
|
||||||
we are free to add improvements to make the code more familiar for users who
|
we are free to add improvements to make the code more familiar for users who
|
||||||
know popular programming languages. In other words: remove weird things that
|
know popular programming languages. In other words: remove weird things that
|
||||||
only Vim uses.
|
only Vim does.
|
||||||
|
|
||||||
We can also remove clutter, mainly things that were done to make Vim script
|
We can also remove clutter, mainly things that were done to make Vim script
|
||||||
backwards compatible with good old Vi commands.
|
backwards compatible with the good old Vi commands.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
- Drop `:call` for calling a function and `:eval` for manipulating data.
|
- Drop `:call` for calling a function and `:eval` for manipulating data.
|
||||||
@ -993,44 +996,26 @@ Examples:
|
|||||||
|
|
||||||
However, this does require that some things need to change:
|
However, this does require that some things need to change:
|
||||||
- Comments start with # instead of ", to avoid confusing them with strings.
|
- Comments start with # instead of ", to avoid confusing them with strings.
|
||||||
|
This is good anyway, it is known from several popular languages.
|
||||||
- Ex command ranges need to be prefixed with a colon, to avoid confusion with
|
- Ex command ranges need to be prefixed with a colon, to avoid confusion with
|
||||||
expressions (single quote can be a string or a mark, "/" can be divide or a
|
expressions (single quote can be a string or a mark, "/" can be divide or a
|
||||||
search command, etc.).
|
search command, etc.).
|
||||||
|
|
||||||
Goal is to limit the differences. A good criteria is that when the old syntax
|
Goal is to limit the differences. A good criteria is that when the old syntax
|
||||||
is used you are very likely to get an error message.
|
is accidentally used you are very likely to get an error message.
|
||||||
|
|
||||||
|
|
||||||
TypeScript syntax and semantics ~
|
Syntax and semantics from popular languages ~
|
||||||
|
|
||||||
Script writers have complained that the Vim script syntax is unexpectedly
|
Script writers have complained that the Vim script syntax is unexpectedly
|
||||||
different from what they are used to. To reduce this complaint popular
|
different from what they are used to. To reduce this complaint popular
|
||||||
languages are used as an example. At the same time, we do not want to abandon
|
languages are used as an example. At the same time, we do not want to abandon
|
||||||
the well-known parts of legacy Vim script.
|
the well-known parts of legacy Vim script.
|
||||||
|
|
||||||
Since Vim already uses `:let` and `:const` and optional type checking is
|
For many things TypeScript is followed. It's a recent language that is
|
||||||
desirable, the JavaScript/TypeScript syntax fits best for variable
|
gaining popularity and has similarities with Vim script. It also has a
|
||||||
declarations: >
|
|
||||||
const greeting = 'hello' # string type is inferred
|
|
||||||
let name: string
|
|
||||||
...
|
|
||||||
name = 'John'
|
|
||||||
|
|
||||||
Expression evaluation was already close to what JavaScript and other languages
|
|
||||||
are doing. Some details are unexpected and can be fixed. For example how the
|
|
||||||
|| and && operators work. Legacy Vim script: >
|
|
||||||
let value = 44
|
|
||||||
...
|
|
||||||
let result = value || 0 # result == 1
|
|
||||||
|
|
||||||
Vim9 script works like JavaScript/TypeScript, keep the value: >
|
|
||||||
let value = 44
|
|
||||||
...
|
|
||||||
let result = value || 0 # result == 44
|
|
||||||
|
|
||||||
Another reason why TypeScript can be used as an example for Vim9 script is the
|
|
||||||
mix of static typing (a variable always has a known value type) and dynamic
|
mix of static typing (a variable always has a known value type) and dynamic
|
||||||
typing (a variable can have different types, this hanges at runtime). Since
|
typing (a variable can have different types, this changes at runtime). Since
|
||||||
legacy Vim script is dynamically typed and a lot of existing functionality
|
legacy Vim script is dynamically typed and a lot of existing functionality
|
||||||
(esp. builtin functions) depends on that, while static typing allows for much
|
(esp. builtin functions) depends on that, while static typing allows for much
|
||||||
faster execution, we need to have this mix in Vim9 script.
|
faster execution, we need to have this mix in Vim9 script.
|
||||||
@ -1054,7 +1039,7 @@ Specific items from TypeScript we avoid:
|
|||||||
- TypeScript can use an expression like "99 || 'yes'" in a condition, but
|
- TypeScript can use an expression like "99 || 'yes'" in a condition, but
|
||||||
cannot assign the value to a boolean. That is inconsistent and can be
|
cannot assign the value to a boolean. That is inconsistent and can be
|
||||||
annoying. Vim recognizes an expression with && or || and allows using the
|
annoying. Vim recognizes an expression with && or || and allows using the
|
||||||
result as a bool.
|
result as a bool. TODO: to be reconsidered
|
||||||
- TypeScript considers an empty string as Falsy, but an empty list or dict as
|
- TypeScript considers an empty string as Falsy, but an empty list or dict as
|
||||||
Truthy. That is inconsistent. In Vim an empty list and dict are also
|
Truthy. That is inconsistent. In Vim an empty list and dict are also
|
||||||
Falsy.
|
Falsy.
|
||||||
@ -1063,6 +1048,80 @@ Specific items from TypeScript we avoid:
|
|||||||
which is more flexible, but is only checked at runtime.
|
which is more flexible, but is only checked at runtime.
|
||||||
|
|
||||||
|
|
||||||
|
Declarations ~
|
||||||
|
|
||||||
|
Legacy Vim script uses `:let` for every assignment, while in Vim9 declarations
|
||||||
|
are used. That is different, thus it's good to use a different command:
|
||||||
|
`:var`. This is used in many languages. The semantics might be slightly
|
||||||
|
different, but it's easily recognized as a declaration.
|
||||||
|
|
||||||
|
Using `:const` for constants is common, but the semantics vary. Some
|
||||||
|
languages only make the variable immutable, others also make the value
|
||||||
|
immutable. Since "final" is well known from Java for only making the variable
|
||||||
|
immutable we decided to use that. And then `:const` can be used for making
|
||||||
|
both immutable. This was also used in legacy Vim script and the meaning is
|
||||||
|
almost the same.
|
||||||
|
|
||||||
|
What we end up with is very similar to Dart: >
|
||||||
|
:var name # mutable variable and value
|
||||||
|
:final name # immutable variable, mutable value
|
||||||
|
:const name # immutable variable and value
|
||||||
|
|
||||||
|
Since legacy and Vim9 script will be mixed and global variables will be
|
||||||
|
shared, optional type checking is desirable. Also, type inference will avoid
|
||||||
|
the need for specifying the type in many cases. The TypeScript syntax fits
|
||||||
|
best for adding types to declarations: >
|
||||||
|
var name: string # string type is specified
|
||||||
|
...
|
||||||
|
name = 'John'
|
||||||
|
const greeting = 'hello' # string type is inferred
|
||||||
|
|
||||||
|
This is how we put types in a declaration: >
|
||||||
|
var mylist: list<string>
|
||||||
|
final mylist: list<string> = ['foo']
|
||||||
|
def Func(arg1: number, arg2: string): bool
|
||||||
|
|
||||||
|
Two alternatives were considered:
|
||||||
|
1. Put the type before the name, like Dart: >
|
||||||
|
var list<string> mylist
|
||||||
|
final list<string> mylist = ['foo']
|
||||||
|
def Func(number arg1, string arg2) bool
|
||||||
|
2. Put the type after the variable name, but do not use a colon, like Go: >
|
||||||
|
var mylist list<string>
|
||||||
|
final mylist list<string> = ['foo']
|
||||||
|
def Func(arg1 number, arg2 string) bool
|
||||||
|
|
||||||
|
The first is more familiar for anyone used to C or Java. The second one
|
||||||
|
doesn't really has an advantage over the first, so let's discard the second.
|
||||||
|
|
||||||
|
Since we use type inference the type can be left out when it can be inferred
|
||||||
|
from the value. This means that after `var` we don't know if a type or a name
|
||||||
|
follows. That makes parsing harder, not only for Vim but also for humans.
|
||||||
|
Also, it will not be allowed to use a variable name that could be a type name,
|
||||||
|
using `var string string` is too confusing.
|
||||||
|
|
||||||
|
The chosen syntax, using a colon to separate the name from the type, adds
|
||||||
|
punctuation, but it actually makes it easier to recognize the parts of a
|
||||||
|
declaration.
|
||||||
|
|
||||||
|
|
||||||
|
Expressions ~
|
||||||
|
|
||||||
|
Expression evaluation was already close to what JavaScript and other languages
|
||||||
|
are doing. Some details are unexpected and can be fixed. For example how the
|
||||||
|
|| and && operators work. Legacy Vim script: >
|
||||||
|
var value = 44
|
||||||
|
...
|
||||||
|
var result = value || 0 # result == 1
|
||||||
|
|
||||||
|
Vim9 script works like JavaScript/TypeScript, keep the value: >
|
||||||
|
var value = 44
|
||||||
|
...
|
||||||
|
var result = value || 0 # result == 44
|
||||||
|
|
||||||
|
TODO: the semantics of || and && need to be reconsidered.
|
||||||
|
|
||||||
|
|
||||||
Import and Export ~
|
Import and Export ~
|
||||||
|
|
||||||
A problem of legacy Vim script is that by default all functions and variables
|
A problem of legacy Vim script is that by default all functions and variables
|
||||||
@ -1122,7 +1181,7 @@ only reported then. In case these errors should be found early, e.g. when
|
|||||||
testing, the `:defcompile` command will help out.
|
testing, the `:defcompile` command will help out.
|
||||||
|
|
||||||
|
|
||||||
Why not use an embeded language? ~
|
Why not use an embedded language? ~
|
||||||
|
|
||||||
Vim supports interfaces to Perl, Python, Lua, Tcl and a few others. But
|
Vim supports interfaces to Perl, Python, Lua, Tcl and a few others. But
|
||||||
these interfaces have never become widely used, for various reasons. When
|
these interfaces have never become widely used, for various reasons. When
|
||||||
|
@ -1513,8 +1513,10 @@ set_one_cmd_context(
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
|
case CMD_final:
|
||||||
case CMD_const:
|
case CMD_const:
|
||||||
case CMD_let:
|
case CMD_let:
|
||||||
|
case CMD_var:
|
||||||
case CMD_if:
|
case CMD_if:
|
||||||
case CMD_elseif:
|
case CMD_elseif:
|
||||||
case CMD_while:
|
case CMD_while:
|
||||||
|
@ -270,4 +270,8 @@ EXTERN char e_variable_is_locked_str[]
|
|||||||
INIT(= N_("E1122: Variable is locked: %s"));
|
INIT(= N_("E1122: Variable is locked: %s"));
|
||||||
EXTERN char e_missing_comma_before_argument_str[]
|
EXTERN char e_missing_comma_before_argument_str[]
|
||||||
INIT(= N_("E1123: Missing comma before argument: %s"));
|
INIT(= N_("E1123: Missing comma before argument: %s"));
|
||||||
|
EXTERN char e_str_cannot_be_used_in_legacy_vim_script[]
|
||||||
|
INIT(= N_("E1124: \"%s\" cannot be used in legacy Vim script"));
|
||||||
|
EXTERN char e_final_requires_a_value[]
|
||||||
|
INIT(= N_("E1125: Final requires a value"));
|
||||||
#endif
|
#endif
|
||||||
|
22
src/eval.c
22
src/eval.c
@ -1213,7 +1213,7 @@ set_var_lval(
|
|||||||
char_u *endp,
|
char_u *endp,
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
int copy,
|
int copy,
|
||||||
int flags, // LET_IS_CONST, LET_FORCEIT, LET_NO_COMMAND
|
int flags, // ASSIGN_CONST, ASSIGN_NO_DECL
|
||||||
char_u *op)
|
char_u *op)
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
@ -1281,7 +1281,7 @@ set_var_lval(
|
|||||||
{
|
{
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
|
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_(e_cannot_mod));
|
emsg(_(e_cannot_mod));
|
||||||
*endp = cc;
|
*endp = cc;
|
||||||
@ -1319,7 +1319,7 @@ set_var_lval(
|
|||||||
listitem_T *ll_li = lp->ll_li;
|
listitem_T *ll_li = lp->ll_li;
|
||||||
int ll_n1 = lp->ll_n1;
|
int ll_n1 = lp->ll_n1;
|
||||||
|
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_("E996: Cannot lock a range"));
|
emsg(_("E996: Cannot lock a range"));
|
||||||
return;
|
return;
|
||||||
@ -1378,7 +1378,7 @@ set_var_lval(
|
|||||||
/*
|
/*
|
||||||
* Assign to a List or Dictionary item.
|
* Assign to a List or Dictionary item.
|
||||||
*/
|
*/
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_("E996: Cannot lock a list or dict"));
|
emsg(_("E996: Cannot lock a list or dict"));
|
||||||
return;
|
return;
|
||||||
@ -1688,7 +1688,7 @@ next_for_item(void *fi_void, char_u *arg)
|
|||||||
{
|
{
|
||||||
forinfo_T *fi = (forinfo_T *)fi_void;
|
forinfo_T *fi = (forinfo_T *)fi_void;
|
||||||
int result;
|
int result;
|
||||||
int flag = in_vim9script() ? LET_NO_COMMAND : 0;
|
int flag = in_vim9script() ? ASSIGN_NO_DECL : 0;
|
||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
|
|
||||||
if (fi->fi_blob != NULL)
|
if (fi->fi_blob != NULL)
|
||||||
@ -1741,11 +1741,12 @@ set_context_for_expression(
|
|||||||
char_u *arg,
|
char_u *arg,
|
||||||
cmdidx_T cmdidx)
|
cmdidx_T cmdidx)
|
||||||
{
|
{
|
||||||
int got_eq = FALSE;
|
int has_expr = cmdidx != CMD_let && cmdidx != CMD_var;
|
||||||
int c;
|
int c;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
|
||||||
if (cmdidx == CMD_let || cmdidx == CMD_const)
|
if (cmdidx == CMD_let || cmdidx == CMD_var
|
||||||
|
|| cmdidx == CMD_const || cmdidx == CMD_final)
|
||||||
{
|
{
|
||||||
xp->xp_context = EXPAND_USER_VARS;
|
xp->xp_context = EXPAND_USER_VARS;
|
||||||
if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
|
if (vim_strpbrk(arg, (char_u *)"\"'+-*/%.=!?~|&$([<>,#") == NULL)
|
||||||
@ -1774,8 +1775,7 @@ set_context_for_expression(
|
|||||||
if (c == '&')
|
if (c == '&')
|
||||||
{
|
{
|
||||||
++xp->xp_pattern;
|
++xp->xp_pattern;
|
||||||
xp->xp_context = cmdidx != CMD_let || got_eq
|
xp->xp_context = has_expr ? EXPAND_EXPRESSION : EXPAND_NOTHING;
|
||||||
? EXPAND_EXPRESSION : EXPAND_NOTHING;
|
|
||||||
}
|
}
|
||||||
else if (c != ' ')
|
else if (c != ' ')
|
||||||
{
|
{
|
||||||
@ -1792,7 +1792,7 @@ set_context_for_expression(
|
|||||||
}
|
}
|
||||||
else if (c == '=')
|
else if (c == '=')
|
||||||
{
|
{
|
||||||
got_eq = TRUE;
|
has_expr = TRUE;
|
||||||
xp->xp_context = EXPAND_EXPRESSION;
|
xp->xp_context = EXPAND_EXPRESSION;
|
||||||
}
|
}
|
||||||
else if (c == '#'
|
else if (c == '#'
|
||||||
@ -1808,7 +1808,7 @@ set_context_for_expression(
|
|||||||
// Function name can start with "<SNR>" and contain '#'.
|
// Function name can start with "<SNR>" and contain '#'.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (cmdidx != CMD_let || got_eq)
|
else if (has_expr)
|
||||||
{
|
{
|
||||||
if (c == '"') // string
|
if (c == '"') // string
|
||||||
{
|
{
|
||||||
|
@ -668,6 +668,25 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get)
|
|||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Vim9 variable declaration:
|
||||||
|
* ":var name"
|
||||||
|
* ":var name: type"
|
||||||
|
* ":var name = expr"
|
||||||
|
* ":var name: type = expr"
|
||||||
|
* etc.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ex_var(exarg_T *eap)
|
||||||
|
{
|
||||||
|
if (!in_vim9script())
|
||||||
|
{
|
||||||
|
semsg(_(e_str_cannot_be_used_in_legacy_vim_script), ":var");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ex_let(eap);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":let" list all variable values
|
* ":let" list all variable values
|
||||||
* ":let var1 var2" list variable values
|
* ":let var1 var2" list variable values
|
||||||
@ -683,6 +702,9 @@ heredoc_get(exarg_T *eap, char_u *cmd, int script_get)
|
|||||||
* ":let var =<< ..." heredoc
|
* ":let var =<< ..." heredoc
|
||||||
* ":let var: string" Vim9 declaration
|
* ":let var: string" Vim9 declaration
|
||||||
*
|
*
|
||||||
|
* ":final var = expr" assignment command.
|
||||||
|
* ":final [var1, var2] = expr" unpack list.
|
||||||
|
*
|
||||||
* ":const" list all variable values
|
* ":const" list all variable values
|
||||||
* ":const var1 var2" list variable values
|
* ":const var1 var2" list variable values
|
||||||
* ":const var = expr" assignment command.
|
* ":const var = expr" assignment command.
|
||||||
@ -702,14 +724,22 @@ ex_let(exarg_T *eap)
|
|||||||
int first = TRUE;
|
int first = TRUE;
|
||||||
int concat;
|
int concat;
|
||||||
int has_assign;
|
int has_assign;
|
||||||
int flags = eap->cmdidx == CMD_const ? LET_IS_CONST : 0;
|
int flags = eap->cmdidx == CMD_const ? ASSIGN_CONST : 0;
|
||||||
int vim9script = in_vim9script();
|
int vim9script = in_vim9script();
|
||||||
|
|
||||||
|
if (eap->cmdidx == CMD_final && !vim9script)
|
||||||
|
{
|
||||||
|
// In legacy Vim script ":final" is short for ":finally".
|
||||||
|
ex_finally(eap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (eap->cmdidx == CMD_const && !vim9script && !eap->forceit)
|
||||||
|
// In legacy Vim script ":const" works like ":final".
|
||||||
|
eap->cmdidx = CMD_final;
|
||||||
|
|
||||||
// detect Vim9 assignment without ":let" or ":const"
|
// detect Vim9 assignment without ":let" or ":const"
|
||||||
if (eap->arg == eap->cmd)
|
if (eap->arg == eap->cmd)
|
||||||
flags |= LET_NO_COMMAND;
|
flags |= ASSIGN_NO_DECL;
|
||||||
if (eap->forceit)
|
|
||||||
flags |= LET_FORCEIT;
|
|
||||||
|
|
||||||
argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
|
argend = skip_var_list(arg, TRUE, &var_count, &semicolon, FALSE);
|
||||||
if (argend == NULL)
|
if (argend == NULL)
|
||||||
@ -787,7 +817,7 @@ ex_let(exarg_T *eap)
|
|||||||
op[1] = NUL;
|
op[1] = NUL;
|
||||||
if (*expr != '=')
|
if (*expr != '=')
|
||||||
{
|
{
|
||||||
if (vim9script && (flags & LET_NO_COMMAND) == 0)
|
if (vim9script && (flags & ASSIGN_NO_DECL) == 0)
|
||||||
{
|
{
|
||||||
// +=, /=, etc. require an existing variable
|
// +=, /=, etc. require an existing variable
|
||||||
semsg(_(e_cannot_use_operator_on_new_variable), eap->arg);
|
semsg(_(e_cannot_use_operator_on_new_variable), eap->arg);
|
||||||
@ -860,7 +890,7 @@ ex_let_vars(
|
|||||||
int copy, // copy values from "tv", don't move
|
int copy, // copy values from "tv", don't move
|
||||||
int semicolon, // from skip_var_list()
|
int semicolon, // from skip_var_list()
|
||||||
int var_count, // from skip_var_list()
|
int var_count, // from skip_var_list()
|
||||||
int flags, // LET_IS_CONST, LET_FORCEIT, LET_NO_COMMAND
|
int flags, // ASSIGN_CONST, ASSIGN_NO_DECL
|
||||||
char_u *op)
|
char_u *op)
|
||||||
{
|
{
|
||||||
char_u *arg = arg_start;
|
char_u *arg = arg_start;
|
||||||
@ -1215,7 +1245,7 @@ ex_let_one(
|
|||||||
char_u *arg, // points to variable name
|
char_u *arg, // points to variable name
|
||||||
typval_T *tv, // value to assign to variable
|
typval_T *tv, // value to assign to variable
|
||||||
int copy, // copy value from "tv"
|
int copy, // copy value from "tv"
|
||||||
int flags, // LET_IS_CONST, LET_FORCEIT, LET_NO_COMMAND
|
int flags, // ASSIGN_CONST, ASSIGN_NO_DECL
|
||||||
char_u *endchars, // valid chars after variable name or NULL
|
char_u *endchars, // valid chars after variable name or NULL
|
||||||
char_u *op) // "+", "-", "." or NULL
|
char_u *op) // "+", "-", "." or NULL
|
||||||
{
|
{
|
||||||
@ -1227,7 +1257,7 @@ ex_let_one(
|
|||||||
int opt_flags;
|
int opt_flags;
|
||||||
char_u *tofree = NULL;
|
char_u *tofree = NULL;
|
||||||
|
|
||||||
if (in_vim9script() && (flags & LET_NO_COMMAND) == 0
|
if (in_vim9script() && (flags & ASSIGN_NO_DECL) == 0
|
||||||
&& vim_strchr((char_u *)"$@&", *arg) != NULL)
|
&& vim_strchr((char_u *)"$@&", *arg) != NULL)
|
||||||
{
|
{
|
||||||
vim9_declare_error(arg);
|
vim9_declare_error(arg);
|
||||||
@ -1237,7 +1267,7 @@ ex_let_one(
|
|||||||
// ":let $VAR = expr": Set environment variable.
|
// ":let $VAR = expr": Set environment variable.
|
||||||
if (*arg == '$')
|
if (*arg == '$')
|
||||||
{
|
{
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_("E996: Cannot lock an environment variable"));
|
emsg(_("E996: Cannot lock an environment variable"));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1289,7 +1319,7 @@ ex_let_one(
|
|||||||
// ":let &g:option = expr": Set global option value.
|
// ":let &g:option = expr": Set global option value.
|
||||||
else if (*arg == '&')
|
else if (*arg == '&')
|
||||||
{
|
{
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_(e_const_option));
|
emsg(_(e_const_option));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1373,7 +1403,7 @@ ex_let_one(
|
|||||||
// ":let @r = expr": Set register contents.
|
// ":let @r = expr": Set register contents.
|
||||||
else if (*arg == '@')
|
else if (*arg == '@')
|
||||||
{
|
{
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_("E996: Cannot lock a register"));
|
emsg(_("E996: Cannot lock a register"));
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2926,7 +2956,7 @@ set_var(
|
|||||||
typval_T *tv,
|
typval_T *tv,
|
||||||
int copy) // make copy of value in "tv"
|
int copy) // make copy of value in "tv"
|
||||||
{
|
{
|
||||||
set_var_const(name, NULL, tv, copy, LET_NO_COMMAND);
|
set_var_const(name, NULL, tv, copy, ASSIGN_NO_DECL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2940,7 +2970,7 @@ set_var_const(
|
|||||||
type_T *type,
|
type_T *type,
|
||||||
typval_T *tv_arg,
|
typval_T *tv_arg,
|
||||||
int copy, // make copy of value in "tv"
|
int copy, // make copy of value in "tv"
|
||||||
int flags) // LET_IS_CONST, LET_FORCEIT, LET_NO_COMMAND
|
int flags) // ASSIGN_CONST, ASSIGN_NO_DECL
|
||||||
{
|
{
|
||||||
typval_T *tv = tv_arg;
|
typval_T *tv = tv_arg;
|
||||||
typval_T bool_tv;
|
typval_T bool_tv;
|
||||||
@ -2960,7 +2990,7 @@ set_var_const(
|
|||||||
|
|
||||||
if (vim9script
|
if (vim9script
|
||||||
&& !is_script_local
|
&& !is_script_local
|
||||||
&& (flags & LET_NO_COMMAND) == 0
|
&& (flags & ASSIGN_NO_DECL) == 0
|
||||||
&& name[1] == ':')
|
&& name[1] == ':')
|
||||||
{
|
{
|
||||||
vim9_declare_error(name);
|
vim9_declare_error(name);
|
||||||
@ -2990,7 +3020,7 @@ set_var_const(
|
|||||||
{
|
{
|
||||||
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
|
if ((di->di_flags & DI_FLAGS_RELOAD) == 0)
|
||||||
{
|
{
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
{
|
{
|
||||||
emsg(_(e_cannot_mod));
|
emsg(_(e_cannot_mod));
|
||||||
goto failed;
|
goto failed;
|
||||||
@ -2998,7 +3028,7 @@ set_var_const(
|
|||||||
|
|
||||||
if (is_script_local && vim9script)
|
if (is_script_local && vim9script)
|
||||||
{
|
{
|
||||||
if ((flags & LET_NO_COMMAND) == 0)
|
if ((flags & ASSIGN_NO_DECL) == 0)
|
||||||
{
|
{
|
||||||
semsg(_(e_redefining_script_item_str), name);
|
semsg(_(e_redefining_script_item_str), name);
|
||||||
goto failed;
|
goto failed;
|
||||||
@ -3094,7 +3124,7 @@ set_var_const(
|
|||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
di->di_flags = DI_FLAGS_ALLOC;
|
di->di_flags = DI_FLAGS_ALLOC;
|
||||||
if (flags & LET_IS_CONST)
|
if (flags & ASSIGN_CONST)
|
||||||
di->di_flags |= DI_FLAGS_LOCK;
|
di->di_flags |= DI_FLAGS_LOCK;
|
||||||
|
|
||||||
if (is_script_local && vim9script)
|
if (is_script_local && vim9script)
|
||||||
@ -3113,7 +3143,7 @@ set_var_const(
|
|||||||
sv->sv_type = typval2type(tv, &si->sn_type_list);
|
sv->sv_type = typval2type(tv, &si->sn_type_list);
|
||||||
else
|
else
|
||||||
sv->sv_type = type;
|
sv->sv_type = type;
|
||||||
sv->sv_const = (flags & LET_IS_CONST);
|
sv->sv_const = (flags & ASSIGN_CONST);
|
||||||
sv->sv_export = is_export;
|
sv->sv_export = is_export;
|
||||||
++si->sn_var_vals.ga_len;
|
++si->sn_var_vals.ga_len;
|
||||||
|
|
||||||
@ -3132,8 +3162,8 @@ set_var_const(
|
|||||||
init_tv(tv);
|
init_tv(tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ":const var = val" locks the value; in Vim9 script only with ":const!"
|
// ":const var = val" locks the value
|
||||||
if ((flags & LET_IS_CONST) && (!vim9script || (flags & LET_FORCEIT)))
|
if (flags & ASSIGN_CONST)
|
||||||
// Like :lockvar! name: lock the value and what it contains, but only
|
// Like :lockvar! name: lock the value and what it contains, but only
|
||||||
// if the reference count is up to one. That locks only literal
|
// if the reference count is up to one. That locks only literal
|
||||||
// values.
|
// values.
|
||||||
|
@ -11,26 +11,26 @@ static const unsigned short cmdidxs1[26] =
|
|||||||
/* d */ 108,
|
/* d */ 108,
|
||||||
/* e */ 133,
|
/* e */ 133,
|
||||||
/* f */ 156,
|
/* f */ 156,
|
||||||
/* g */ 172,
|
/* g */ 173,
|
||||||
/* h */ 178,
|
/* h */ 179,
|
||||||
/* i */ 187,
|
/* i */ 188,
|
||||||
/* j */ 206,
|
/* j */ 207,
|
||||||
/* k */ 208,
|
/* k */ 209,
|
||||||
/* l */ 213,
|
/* l */ 214,
|
||||||
/* m */ 275,
|
/* m */ 276,
|
||||||
/* n */ 293,
|
/* n */ 294,
|
||||||
/* o */ 313,
|
/* o */ 314,
|
||||||
/* p */ 325,
|
/* p */ 326,
|
||||||
/* q */ 364,
|
/* q */ 365,
|
||||||
/* r */ 367,
|
/* r */ 368,
|
||||||
/* s */ 387,
|
/* s */ 388,
|
||||||
/* t */ 456,
|
/* t */ 457,
|
||||||
/* u */ 501,
|
/* u */ 502,
|
||||||
/* v */ 512,
|
/* v */ 513,
|
||||||
/* w */ 531,
|
/* w */ 533,
|
||||||
/* x */ 545,
|
/* x */ 547,
|
||||||
/* y */ 555,
|
/* y */ 557,
|
||||||
/* z */ 556
|
/* z */ 558
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -46,7 +46,7 @@ static const unsigned char cmdidxs2[26][26] =
|
|||||||
/* c */ { 3, 12, 16, 18, 20, 22, 25, 0, 0, 0, 0, 33, 37, 40, 46, 56, 58, 59, 60, 0, 62, 0, 65, 0, 0, 0 },
|
/* c */ { 3, 12, 16, 18, 20, 22, 25, 0, 0, 0, 0, 33, 37, 40, 46, 56, 58, 59, 60, 0, 62, 0, 65, 0, 0, 0 },
|
||||||
/* d */ { 0, 0, 0, 0, 0, 0, 0, 0, 8, 18, 0, 19, 0, 0, 20, 0, 0, 22, 23, 0, 0, 0, 0, 0, 0, 0 },
|
/* d */ { 0, 0, 0, 0, 0, 0, 0, 0, 8, 18, 0, 19, 0, 0, 20, 0, 0, 22, 23, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
/* e */ { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 10, 0, 0, 0, 0, 0, 0, 0, 17, 0, 18, 0, 0 },
|
/* e */ { 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 7, 9, 10, 0, 0, 0, 0, 0, 0, 0, 17, 0, 18, 0, 0 },
|
||||||
/* f */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0 },
|
/* f */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0 },
|
||||||
/* g */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 4, 5, 0, 0, 0, 0 },
|
/* g */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 0, 4, 5, 0, 0, 0, 0 },
|
||||||
/* h */ { 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
/* h */ { 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
/* i */ { 1, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 5, 6, 0, 0, 0, 0, 0, 14, 0, 16, 0, 0, 0, 0, 0 },
|
/* i */ { 1, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 5, 6, 0, 0, 0, 0, 0, 14, 0, 16, 0, 0, 0, 0, 0 },
|
||||||
@ -62,11 +62,11 @@ static const unsigned char cmdidxs2[26][26] =
|
|||||||
/* s */ { 2, 6, 15, 0, 19, 23, 0, 25, 26, 0, 0, 29, 31, 35, 39, 41, 0, 50, 0, 51, 0, 63, 64, 0, 65, 0 },
|
/* s */ { 2, 6, 15, 0, 19, 23, 0, 25, 26, 0, 0, 29, 31, 35, 39, 41, 0, 50, 0, 51, 0, 63, 64, 0, 65, 0 },
|
||||||
/* t */ { 2, 0, 19, 0, 24, 26, 0, 27, 0, 28, 0, 29, 33, 36, 38, 39, 0, 40, 42, 0, 43, 0, 0, 0, 0, 0 },
|
/* t */ { 2, 0, 19, 0, 24, 26, 0, 27, 0, 28, 0, 29, 33, 36, 38, 39, 0, 40, 42, 0, 43, 0, 0, 0, 0, 0 },
|
||||||
/* u */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
/* u */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
/* v */ { 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 10, 13, 0, 0, 0, 0, 16, 0, 17, 0, 0, 0, 0, 0 },
|
/* v */ { 1, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 11, 14, 0, 0, 0, 0, 17, 0, 18, 0, 0, 0, 0, 0 },
|
||||||
/* w */ { 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 8, 0, 9, 10, 0, 0, 0, 12, 13, 0, 0, 0, 0 },
|
/* w */ { 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0, 8, 0, 9, 10, 0, 0, 0, 12, 13, 0, 0, 0, 0 },
|
||||||
/* x */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 0, 0, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0 },
|
/* x */ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 0, 0, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0 },
|
||||||
/* y */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
/* y */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
/* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int command_count = 569;
|
static const int command_count = 571;
|
||||||
|
@ -592,6 +592,9 @@ EXCMD(CMD_filter, "filter", ex_wrongmodifier,
|
|||||||
EXCMD(CMD_find, "find", ex_find,
|
EXCMD(CMD_find, "find", ex_find,
|
||||||
EX_RANGE|EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG,
|
EX_RANGE|EX_BANG|EX_FILE1|EX_CMDARG|EX_ARGOPT|EX_TRLBAR|EX_NEEDARG,
|
||||||
ADDR_OTHER),
|
ADDR_OTHER),
|
||||||
|
EXCMD(CMD_final, "final", ex_let,
|
||||||
|
EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
||||||
|
ADDR_NONE),
|
||||||
EXCMD(CMD_finally, "finally", ex_finally,
|
EXCMD(CMD_finally, "finally", ex_finally,
|
||||||
EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
EX_TRLBAR|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
@ -1648,6 +1651,9 @@ EXCMD(CMD_update, "update", ex_update,
|
|||||||
EXCMD(CMD_vglobal, "vglobal", ex_global,
|
EXCMD(CMD_vglobal, "vglobal", ex_global,
|
||||||
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK,
|
EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_DFLALL|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_LINES),
|
ADDR_LINES),
|
||||||
|
EXCMD(CMD_var, "var", ex_var,
|
||||||
|
EX_EXTRA|EX_NOTRLCOM|EX_SBOXOK|EX_CMDWIN|EX_LOCK_OK,
|
||||||
|
ADDR_NONE),
|
||||||
EXCMD(CMD_version, "version", ex_version,
|
EXCMD(CMD_version, "version", ex_version,
|
||||||
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK,
|
||||||
ADDR_NONE),
|
ADDR_NONE),
|
||||||
|
@ -2421,6 +2421,7 @@ do_one_cmd(
|
|||||||
case CMD_eval:
|
case CMD_eval:
|
||||||
case CMD_execute:
|
case CMD_execute:
|
||||||
case CMD_filter:
|
case CMD_filter:
|
||||||
|
case CMD_final:
|
||||||
case CMD_help:
|
case CMD_help:
|
||||||
case CMD_hide:
|
case CMD_hide:
|
||||||
case CMD_ijump:
|
case CMD_ijump:
|
||||||
@ -2442,9 +2443,9 @@ do_one_cmd(
|
|||||||
case CMD_noswapfile:
|
case CMD_noswapfile:
|
||||||
case CMD_perl:
|
case CMD_perl:
|
||||||
case CMD_psearch:
|
case CMD_psearch:
|
||||||
case CMD_python:
|
|
||||||
case CMD_py3:
|
case CMD_py3:
|
||||||
case CMD_python3:
|
case CMD_python3:
|
||||||
|
case CMD_python:
|
||||||
case CMD_return:
|
case CMD_return:
|
||||||
case CMD_rightbelow:
|
case CMD_rightbelow:
|
||||||
case CMD_ruby:
|
case CMD_ruby:
|
||||||
@ -2460,6 +2461,7 @@ do_one_cmd(
|
|||||||
case CMD_topleft:
|
case CMD_topleft:
|
||||||
case CMD_unlet:
|
case CMD_unlet:
|
||||||
case CMD_unlockvar:
|
case CMD_unlockvar:
|
||||||
|
case CMD_var:
|
||||||
case CMD_verbose:
|
case CMD_verbose:
|
||||||
case CMD_vertical:
|
case CMD_vertical:
|
||||||
case CMD_wincmd:
|
case CMD_wincmd:
|
||||||
@ -3244,7 +3246,7 @@ find_ex_command(
|
|||||||
if (skip_expr(&after) == OK
|
if (skip_expr(&after) == OK
|
||||||
&& (*after == '='
|
&& (*after == '='
|
||||||
|| (*after != NUL && after[1] == '=')))
|
|| (*after != NUL && after[1] == '=')))
|
||||||
eap->cmdidx = CMD_let;
|
eap->cmdidx = CMD_var;
|
||||||
else
|
else
|
||||||
eap->cmdidx = CMD_eval;
|
eap->cmdidx = CMD_eval;
|
||||||
--emsg_silent;
|
--emsg_silent;
|
||||||
@ -3268,7 +3270,7 @@ find_ex_command(
|
|||||||
}
|
}
|
||||||
if (p > eap->cmd && *skipwhite(p) == '=')
|
if (p > eap->cmd && *skipwhite(p) == '=')
|
||||||
{
|
{
|
||||||
eap->cmdidx = CMD_let;
|
eap->cmdidx = CMD_var;
|
||||||
return eap->cmd;
|
return eap->cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3287,7 +3289,7 @@ find_ex_command(
|
|||||||
|| *eap->cmd == '@'
|
|| *eap->cmd == '@'
|
||||||
|| lookup(eap->cmd, p - eap->cmd, cctx) != NULL)
|
|| lookup(eap->cmd, p - eap->cmd, cctx) != NULL)
|
||||||
{
|
{
|
||||||
eap->cmdidx = CMD_let;
|
eap->cmdidx = CMD_var;
|
||||||
return eap->cmd;
|
return eap->cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ int get_spellword(list_T *list, char_u **pp);
|
|||||||
void prepare_vimvar(int idx, typval_T *save_tv);
|
void prepare_vimvar(int idx, typval_T *save_tv);
|
||||||
void restore_vimvar(int idx, typval_T *save_tv);
|
void restore_vimvar(int idx, typval_T *save_tv);
|
||||||
list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
|
list_T *heredoc_get(exarg_T *eap, char_u *cmd, int script_get);
|
||||||
|
void ex_var(exarg_T *eap);
|
||||||
void ex_let(exarg_T *eap);
|
void ex_let(exarg_T *eap);
|
||||||
int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, int var_count, int flags, char_u *op);
|
int ex_let_vars(char_u *arg_start, typval_T *tv, int copy, int semicolon, int var_count, int flags, char_u *op);
|
||||||
char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int *semicolon, int silent);
|
char_u *skip_var_list(char_u *arg, int include_type, int *var_count, int *semicolon, int silent);
|
||||||
|
@ -12,30 +12,30 @@ let g:alist = [7]
|
|||||||
let g:astring = 'text'
|
let g:astring = 'text'
|
||||||
|
|
||||||
def Test_assignment_bool()
|
def Test_assignment_bool()
|
||||||
let bool1: bool = true
|
var bool1: bool = true
|
||||||
assert_equal(v:true, bool1)
|
assert_equal(v:true, bool1)
|
||||||
let bool2: bool = false
|
var bool2: bool = false
|
||||||
assert_equal(v:false, bool2)
|
assert_equal(v:false, bool2)
|
||||||
|
|
||||||
let bool3: bool = 0
|
var bool3: bool = 0
|
||||||
assert_equal(false, bool3)
|
assert_equal(false, bool3)
|
||||||
let bool4: bool = 1
|
var bool4: bool = 1
|
||||||
assert_equal(true, bool4)
|
assert_equal(true, bool4)
|
||||||
|
|
||||||
let bool5: bool = 'yes' && 'no'
|
var bool5: bool = 'yes' && 'no'
|
||||||
assert_equal(true, bool5)
|
assert_equal(true, bool5)
|
||||||
let bool6: bool = [] && 99
|
var bool6: bool = [] && 99
|
||||||
assert_equal(false, bool6)
|
assert_equal(false, bool6)
|
||||||
let bool7: bool = [] || #{a: 1} && 99
|
var bool7: bool = [] || #{a: 1} && 99
|
||||||
assert_equal(true, bool7)
|
assert_equal(true, bool7)
|
||||||
|
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
def GetFlag(): bool
|
def GetFlag(): bool
|
||||||
let flag: bool = 1
|
var flag: bool = 1
|
||||||
return flag
|
return flag
|
||||||
enddef
|
enddef
|
||||||
let flag: bool = GetFlag()
|
var flag: bool = GetFlag()
|
||||||
assert_equal(true, flag)
|
assert_equal(true, flag)
|
||||||
flag = 0
|
flag = 0
|
||||||
assert_equal(false, flag)
|
assert_equal(false, flag)
|
||||||
@ -47,41 +47,42 @@ def Test_assignment_bool()
|
|||||||
assert_equal(false, flag)
|
assert_equal(false, flag)
|
||||||
END
|
END
|
||||||
CheckScriptSuccess(lines)
|
CheckScriptSuccess(lines)
|
||||||
CheckDefAndScriptFailure(['let x: bool = 2'], 'E1012:')
|
CheckDefAndScriptFailure(['var x: bool = 2'], 'E1012:')
|
||||||
CheckDefAndScriptFailure(['let x: bool = -1'], 'E1012:')
|
CheckDefAndScriptFailure(['var x: bool = -1'], 'E1012:')
|
||||||
CheckDefAndScriptFailure(['let x: bool = [1]'], 'E1012:')
|
CheckDefAndScriptFailure(['var x: bool = [1]'], 'E1012:')
|
||||||
CheckDefAndScriptFailure(['let x: bool = {}'], 'E1012:')
|
CheckDefAndScriptFailure(['var x: bool = {}'], 'E1012:')
|
||||||
CheckDefAndScriptFailure(['let x: bool = "x"'], 'E1012:')
|
CheckDefAndScriptFailure(['var x: bool = "x"'], 'E1012:')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_syntax()
|
def Test_syntax()
|
||||||
let var = 234
|
var var = 234
|
||||||
let other: list<string> = ['asdf']
|
var other: list<string> = ['asdf']
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment()
|
def Test_assignment()
|
||||||
CheckDefFailure(['let x:string'], 'E1069:')
|
CheckDefFailure(['var x:string'], 'E1069:')
|
||||||
CheckDefFailure(['let x:string = "x"'], 'E1069:')
|
CheckDefFailure(['var x:string = "x"'], 'E1069:')
|
||||||
CheckDefFailure(['let a:string = "x"'], 'E1069:')
|
CheckDefFailure(['var a:string = "x"'], 'E1069:')
|
||||||
CheckDefFailure(['let lambda = {-> "lambda"}'], 'E704:')
|
CheckDefFailure(['var lambda = {-> "lambda"}'], 'E704:')
|
||||||
|
CheckScriptFailure(['var x = "x"'], 'E1124:')
|
||||||
|
|
||||||
let nr: number = 1234
|
var nr: number = 1234
|
||||||
CheckDefFailure(['let nr: number = "asdf"'], 'E1012:')
|
CheckDefFailure(['var nr: number = "asdf"'], 'E1012:')
|
||||||
|
|
||||||
let a: number = 6 #comment
|
var a: number = 6 #comment
|
||||||
assert_equal(6, a)
|
assert_equal(6, a)
|
||||||
|
|
||||||
if has('channel')
|
if has('channel')
|
||||||
let chan1: channel
|
var chan1: channel
|
||||||
let job1: job
|
var job1: job
|
||||||
let job2: job = job_start('willfail')
|
var job2: job = job_start('willfail')
|
||||||
endif
|
endif
|
||||||
if has('float')
|
if has('float')
|
||||||
let float1: float = 3.4
|
var float1: float = 3.4
|
||||||
endif
|
endif
|
||||||
let Funky1: func
|
var Funky1: func
|
||||||
let Funky2: func = function('len')
|
var Funky2: func = function('len')
|
||||||
let Party2: func = funcref('g:Test_syntax')
|
var Party2: func = funcref('g:Test_syntax')
|
||||||
|
|
||||||
g:newvar = 'new' #comment
|
g:newvar = 'new' #comment
|
||||||
assert_equal('new', g:newvar)
|
assert_equal('new', g:newvar)
|
||||||
@ -97,7 +98,7 @@ def Test_assignment()
|
|||||||
assert_equal('foobar', $ENVVAR)
|
assert_equal('foobar', $ENVVAR)
|
||||||
$ENVVAR = ''
|
$ENVVAR = ''
|
||||||
|
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
$ENVVAR = 'barfoo'
|
$ENVVAR = 'barfoo'
|
||||||
assert_equal('barfoo', $ENVVAR)
|
assert_equal('barfoo', $ENVVAR)
|
||||||
@ -126,15 +127,15 @@ def Test_assignment()
|
|||||||
assert_equal(2, &ts)
|
assert_equal(2, &ts)
|
||||||
|
|
||||||
if has('float')
|
if has('float')
|
||||||
let f100: float = 100.0
|
var f100: float = 100.0
|
||||||
f100 /= 5
|
f100 /= 5
|
||||||
assert_equal(20.0, f100)
|
assert_equal(20.0, f100)
|
||||||
|
|
||||||
let f200: float = 200.0
|
var f200: float = 200.0
|
||||||
f200 /= 5.0
|
f200 /= 5.0
|
||||||
assert_equal(40.0, f200)
|
assert_equal(40.0, f200)
|
||||||
|
|
||||||
CheckDefFailure(['let nr: number = 200', 'nr /= 5.0'], 'E1012:')
|
CheckDefFailure(['var nr: number = 200', 'nr /= 5.0'], 'E1012:')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
@ -163,11 +164,11 @@ def Test_assignment()
|
|||||||
CheckDefFailure(['&path += 3'], 'E1012:')
|
CheckDefFailure(['&path += 3'], 'E1012:')
|
||||||
CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
|
CheckDefExecFailure(['&bs = "asdf"'], 'E474:')
|
||||||
# test freeing ISN_STOREOPT
|
# test freeing ISN_STOREOPT
|
||||||
CheckDefFailure(['&ts = 3', 'let asdf'], 'E1022:')
|
CheckDefFailure(['&ts = 3', 'var asdf'], 'E1022:')
|
||||||
&ts = 8
|
&ts = 8
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
let save_TI = &t_TI
|
var save_TI = &t_TI
|
||||||
&t_TI = ''
|
&t_TI = ''
|
||||||
assert_equal('', &t_TI)
|
assert_equal('', &t_TI)
|
||||||
&t_TI = 'xxx'
|
&t_TI = 'xxx'
|
||||||
@ -179,8 +180,8 @@ def Test_assignment()
|
|||||||
CheckDefFailure(['&t_TI = 123'], 'E1012:')
|
CheckDefFailure(['&t_TI = 123'], 'E1012:')
|
||||||
CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
|
CheckScriptFailure(['vim9script', '&t_TI = 123'], 'E928:')
|
||||||
|
|
||||||
CheckDefFailure(['let s:var = 123'], 'E1101:')
|
CheckDefFailure(['var s:var = 123'], 'E1101:')
|
||||||
CheckDefFailure(['let s:var: number'], 'E1101:')
|
CheckDefFailure(['var s:var: number'], 'E1101:')
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
@ -217,20 +218,20 @@ def Test_assignment()
|
|||||||
|
|
||||||
# this should not leak
|
# this should not leak
|
||||||
if 0
|
if 0
|
||||||
let text =<< trim END
|
var text =<< trim END
|
||||||
some text
|
some text
|
||||||
END
|
END
|
||||||
endif
|
endif
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_extend_list()
|
def Test_extend_list()
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let l: list<number>
|
var l: list<number>
|
||||||
l += [123]
|
l += [123]
|
||||||
assert_equal([123], l)
|
assert_equal([123], l)
|
||||||
|
|
||||||
let d: dict<number>
|
var d: dict<number>
|
||||||
d['one'] = 1
|
d['one'] = 1
|
||||||
assert_equal(#{one: 1}, d)
|
assert_equal(#{one: 1}, d)
|
||||||
END
|
END
|
||||||
@ -239,41 +240,41 @@ enddef
|
|||||||
|
|
||||||
def Test_single_letter_vars()
|
def Test_single_letter_vars()
|
||||||
# single letter variables
|
# single letter variables
|
||||||
let a: number = 123
|
var a: number = 123
|
||||||
a = 123
|
a = 123
|
||||||
assert_equal(123, a)
|
assert_equal(123, a)
|
||||||
let b: number
|
var b: number
|
||||||
b = 123
|
b = 123
|
||||||
assert_equal(123, b)
|
assert_equal(123, b)
|
||||||
let g: number
|
var g: number
|
||||||
g = 123
|
g = 123
|
||||||
assert_equal(123, g)
|
assert_equal(123, g)
|
||||||
let s: number
|
var s: number
|
||||||
s = 123
|
s = 123
|
||||||
assert_equal(123, s)
|
assert_equal(123, s)
|
||||||
let t: number
|
var t: number
|
||||||
t = 123
|
t = 123
|
||||||
assert_equal(123, t)
|
assert_equal(123, t)
|
||||||
let v: number
|
var v: number
|
||||||
v = 123
|
v = 123
|
||||||
assert_equal(123, v)
|
assert_equal(123, v)
|
||||||
let w: number
|
var w: number
|
||||||
w = 123
|
w = 123
|
||||||
assert_equal(123, w)
|
assert_equal(123, w)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_vim9_single_char_vars()
|
def Test_vim9_single_char_vars()
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
|
|
||||||
# single character variable declarations work
|
# single character variable declarations work
|
||||||
let a: string
|
var a: string
|
||||||
let b: number
|
var b: number
|
||||||
let l: list<any>
|
var l: list<any>
|
||||||
let s: string
|
var s: string
|
||||||
let t: number
|
var t: number
|
||||||
let v: number
|
var v: number
|
||||||
let w: number
|
var w: number
|
||||||
|
|
||||||
# script-local variables can be used without s: prefix
|
# script-local variables can be used without s: prefix
|
||||||
a = 'script-a'
|
a = 'script-a'
|
||||||
@ -298,14 +299,14 @@ def Test_vim9_single_char_vars()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_list()
|
def Test_assignment_list()
|
||||||
let list1: list<bool> = [false, true, false]
|
var list1: list<bool> = [false, true, false]
|
||||||
let list2: list<number> = [1, 2, 3]
|
var list2: list<number> = [1, 2, 3]
|
||||||
let list3: list<string> = ['sdf', 'asdf']
|
var list3: list<string> = ['sdf', 'asdf']
|
||||||
let list4: list<any> = ['yes', true, 1234]
|
var list4: list<any> = ['yes', true, 1234]
|
||||||
let list5: list<blob> = [0z01, 0z02]
|
var list5: list<blob> = [0z01, 0z02]
|
||||||
|
|
||||||
let listS: list<string> = []
|
var listS: list<string> = []
|
||||||
let listN: list<number> = []
|
var listN: list<number> = []
|
||||||
|
|
||||||
assert_equal([1, 2, 3], list2)
|
assert_equal([1, 2, 3], list2)
|
||||||
list2[-1] = 99
|
list2[-1] = 99
|
||||||
@ -320,19 +321,19 @@ def Test_assignment_list()
|
|||||||
list3 += ['end']
|
list3 += ['end']
|
||||||
assert_equal(['sdf', 'asdf', 'end'], list3)
|
assert_equal(['sdf', 'asdf', 'end'], list3)
|
||||||
|
|
||||||
CheckDefExecFailure(['let ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
|
CheckDefExecFailure(['var ll = [1, 2, 3]', 'll[-4] = 6'], 'E684:')
|
||||||
CheckDefExecFailure(['let [v1, v2] = [1, 2]'], 'E1092:')
|
CheckDefExecFailure(['var [v1, v2] = [1, 2]'], 'E1092:')
|
||||||
|
|
||||||
# type becomes list<any>
|
# type becomes list<any>
|
||||||
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
|
var somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_list_vim9script()
|
def Test_assignment_list_vim9script()
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let v1: number
|
var v1: number
|
||||||
let v2: number
|
var v2: number
|
||||||
let v3: number
|
var v3: number
|
||||||
[v1, v2, v3] = [1, 2, 3]
|
[v1, v2, v3] = [1, 2, 3]
|
||||||
assert_equal([1, 2, 3], [v1, v2, v3])
|
assert_equal([1, 2, 3], [v1, v2, v3])
|
||||||
END
|
END
|
||||||
@ -340,27 +341,27 @@ def Test_assignment_list_vim9script()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_dict()
|
def Test_assignment_dict()
|
||||||
let dict1: dict<bool> = #{one: false, two: true}
|
var dict1: dict<bool> = #{one: false, two: true}
|
||||||
let dict2: dict<number> = #{one: 1, two: 2}
|
var dict2: dict<number> = #{one: 1, two: 2}
|
||||||
let dict3: dict<string> = #{key: 'value'}
|
var dict3: dict<string> = #{key: 'value'}
|
||||||
let dict4: dict<any> = #{one: 1, two: '2'}
|
var dict4: dict<any> = #{one: 1, two: '2'}
|
||||||
let dict5: dict<blob> = #{one: 0z01, two: 0z02}
|
var dict5: dict<blob> = #{one: 0z01, two: 0z02}
|
||||||
|
|
||||||
# overwrite
|
# overwrite
|
||||||
dict3['key'] = 'another'
|
dict3['key'] = 'another'
|
||||||
|
|
||||||
# empty key can be used
|
# empty key can be used
|
||||||
let dd = {}
|
var dd = {}
|
||||||
dd[""] = 6
|
dd[""] = 6
|
||||||
assert_equal({'': 6}, dd)
|
assert_equal({'': 6}, dd)
|
||||||
|
|
||||||
# type becomes dict<any>
|
# type becomes dict<any>
|
||||||
let somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
|
var somedict = rand() > 0 ? #{a: 1, b: 2} : #{a: 'a', b: 'b'}
|
||||||
|
|
||||||
# assignment to script-local dict
|
# assignment to script-local dict
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let test: dict<any> = {}
|
var test: dict<any> = {}
|
||||||
def FillDict(): dict<any>
|
def FillDict(): dict<any>
|
||||||
test['a'] = 43
|
test['a'] = 43
|
||||||
return test
|
return test
|
||||||
@ -371,7 +372,7 @@ def Test_assignment_dict()
|
|||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let test: dict<any>
|
var test: dict<any>
|
||||||
def FillDict(): dict<any>
|
def FillDict(): dict<any>
|
||||||
test['a'] = 43
|
test['a'] = 43
|
||||||
return test
|
return test
|
||||||
@ -408,7 +409,7 @@ enddef
|
|||||||
def Test_assignment_local()
|
def Test_assignment_local()
|
||||||
# Test in a separated file in order not to the current buffer/window/tab is
|
# Test in a separated file in order not to the current buffer/window/tab is
|
||||||
# changed.
|
# changed.
|
||||||
let script_lines: list<string> =<< trim END
|
var script_lines: list<string> =<< trim END
|
||||||
let b:existing = 'yes'
|
let b:existing = 'yes'
|
||||||
let w:existing = 'yes'
|
let w:existing = 'yes'
|
||||||
let t:existing = 'yes'
|
let t:existing = 'yes'
|
||||||
@ -446,37 +447,37 @@ enddef
|
|||||||
def Test_assignment_default()
|
def Test_assignment_default()
|
||||||
|
|
||||||
# Test default values.
|
# Test default values.
|
||||||
let thebool: bool
|
var thebool: bool
|
||||||
assert_equal(v:false, thebool)
|
assert_equal(v:false, thebool)
|
||||||
|
|
||||||
let thenumber: number
|
var thenumber: number
|
||||||
assert_equal(0, thenumber)
|
assert_equal(0, thenumber)
|
||||||
|
|
||||||
if has('float')
|
if has('float')
|
||||||
let thefloat: float
|
var thefloat: float
|
||||||
assert_equal(0.0, thefloat)
|
assert_equal(0.0, thefloat)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let thestring: string
|
var thestring: string
|
||||||
assert_equal('', thestring)
|
assert_equal('', thestring)
|
||||||
|
|
||||||
let theblob: blob
|
var theblob: blob
|
||||||
assert_equal(0z, theblob)
|
assert_equal(0z, theblob)
|
||||||
|
|
||||||
let Thefunc: func
|
var Thefunc: func
|
||||||
assert_equal(test_null_function(), Thefunc)
|
assert_equal(test_null_function(), Thefunc)
|
||||||
|
|
||||||
let thelist: list<any>
|
var thelist: list<any>
|
||||||
assert_equal([], thelist)
|
assert_equal([], thelist)
|
||||||
|
|
||||||
let thedict: dict<any>
|
var thedict: dict<any>
|
||||||
assert_equal({}, thedict)
|
assert_equal({}, thedict)
|
||||||
|
|
||||||
if has('channel')
|
if has('channel')
|
||||||
let thejob: job
|
var thejob: job
|
||||||
assert_equal(test_null_job(), thejob)
|
assert_equal(test_null_job(), thejob)
|
||||||
|
|
||||||
let thechannel: channel
|
var thechannel: channel
|
||||||
assert_equal(test_null_channel(), thechannel)
|
assert_equal(test_null_channel(), thechannel)
|
||||||
|
|
||||||
if has('unix') && executable('cat')
|
if has('unix') && executable('cat')
|
||||||
@ -487,14 +488,14 @@ def Test_assignment_default()
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let nr = 1234 | nr = 5678
|
var nr = 1234 | nr = 5678
|
||||||
assert_equal(5678, nr)
|
assert_equal(5678, nr)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_var_list()
|
def Test_assignment_var_list()
|
||||||
let v1: string
|
var v1: string
|
||||||
let v2: string
|
var v2: string
|
||||||
let vrem: list<string>
|
var vrem: list<string>
|
||||||
[v1] = ['aaa']
|
[v1] = ['aaa']
|
||||||
assert_equal('aaa', v1)
|
assert_equal('aaa', v1)
|
||||||
|
|
||||||
@ -519,18 +520,18 @@ def Test_assignment_var_list()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_vim9script()
|
def Test_assignment_vim9script()
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
def Func(): list<number>
|
def Func(): list<number>
|
||||||
return [1, 2]
|
return [1, 2]
|
||||||
enddef
|
enddef
|
||||||
let var1: number
|
var var1: number
|
||||||
let var2: number
|
var var2: number
|
||||||
[var1, var2] =
|
[var1, var2] =
|
||||||
Func()
|
Func()
|
||||||
assert_equal(1, var1)
|
assert_equal(1, var1)
|
||||||
assert_equal(2, var2)
|
assert_equal(2, var2)
|
||||||
let ll =
|
var ll =
|
||||||
Func()
|
Func()
|
||||||
assert_equal([1, 2], ll)
|
assert_equal([1, 2], ll)
|
||||||
|
|
||||||
@ -551,15 +552,15 @@ def Test_assignment_vim9script()
|
|||||||
assert_equal('plus', @+)
|
assert_equal('plus', @+)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let a: number = 123
|
var a: number = 123
|
||||||
assert_equal(123, a)
|
assert_equal(123, a)
|
||||||
let s: string = 'yes'
|
var s: string = 'yes'
|
||||||
assert_equal('yes', s)
|
assert_equal('yes', s)
|
||||||
let b: number = 42
|
var b: number = 42
|
||||||
assert_equal(42, b)
|
assert_equal(42, b)
|
||||||
let w: number = 43
|
var w: number = 43
|
||||||
assert_equal(43, w)
|
assert_equal(43, w)
|
||||||
let t: number = 44
|
var t: number = 44
|
||||||
assert_equal(44, t)
|
assert_equal(44, t)
|
||||||
END
|
END
|
||||||
CheckScriptSuccess(lines)
|
CheckScriptSuccess(lines)
|
||||||
@ -571,80 +572,80 @@ def Mess(): string
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assignment_failure()
|
def Test_assignment_failure()
|
||||||
CheckDefFailure(['let var=234'], 'E1004:')
|
CheckDefFailure(['var var=234'], 'E1004:')
|
||||||
CheckDefFailure(['let var =234'], 'E1004:')
|
CheckDefFailure(['var var =234'], 'E1004:')
|
||||||
CheckDefFailure(['let var= 234'], 'E1004:')
|
CheckDefFailure(['var var= 234'], 'E1004:')
|
||||||
|
|
||||||
CheckScriptFailure(['vim9script', 'let var=234'], 'E1004:')
|
CheckScriptFailure(['vim9script', 'var var=234'], 'E1004:')
|
||||||
CheckScriptFailure(['vim9script', 'let var=234'], "before and after '='")
|
CheckScriptFailure(['vim9script', 'var var=234'], "before and after '='")
|
||||||
CheckScriptFailure(['vim9script', 'let var =234'], 'E1004:')
|
CheckScriptFailure(['vim9script', 'var var =234'], 'E1004:')
|
||||||
CheckScriptFailure(['vim9script', 'let var= 234'], 'E1004:')
|
CheckScriptFailure(['vim9script', 'var var= 234'], 'E1004:')
|
||||||
CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], 'E1004:')
|
CheckScriptFailure(['vim9script', 'var var = 234', 'var+=234'], 'E1004:')
|
||||||
CheckScriptFailure(['vim9script', 'let var = 234', 'var+=234'], "before and after '+='")
|
CheckScriptFailure(['vim9script', 'var var = 234', 'var+=234'], "before and after '+='")
|
||||||
CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], 'E1004:')
|
CheckScriptFailure(['vim9script', 'var var = "x"', 'var..="y"'], 'E1004:')
|
||||||
CheckScriptFailure(['vim9script', 'let var = "x"', 'var..="y"'], "before and after '..='")
|
CheckScriptFailure(['vim9script', 'var var = "x"', 'var..="y"'], "before and after '..='")
|
||||||
|
|
||||||
CheckDefFailure(['let true = 1'], 'E1034:')
|
CheckDefFailure(['var true = 1'], 'E1034:')
|
||||||
CheckDefFailure(['let false = 1'], 'E1034:')
|
CheckDefFailure(['var false = 1'], 'E1034:')
|
||||||
|
|
||||||
CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
|
CheckDefFailure(['[a; b; c] = g:list'], 'E452:')
|
||||||
CheckDefExecFailure(['let a: number',
|
CheckDefExecFailure(['var a: number',
|
||||||
'[a] = test_null_list()'], 'E1093:')
|
'[a] = test_null_list()'], 'E1093:')
|
||||||
CheckDefExecFailure(['let a: number',
|
CheckDefExecFailure(['var a: number',
|
||||||
'[a] = []'], 'E1093:')
|
'[a] = []'], 'E1093:')
|
||||||
CheckDefExecFailure(['let x: number',
|
CheckDefExecFailure(['var x: number',
|
||||||
'let y: number',
|
'var y: number',
|
||||||
'[x, y] = [1]'], 'E1093:')
|
'[x, y] = [1]'], 'E1093:')
|
||||||
CheckDefExecFailure(['let x: number',
|
CheckDefExecFailure(['var x: number',
|
||||||
'let y: number',
|
'var y: number',
|
||||||
'let z: list<number>',
|
'var z: list<number>',
|
||||||
'[x, y; z] = [1]'], 'E1093:')
|
'[x, y; z] = [1]'], 'E1093:')
|
||||||
|
|
||||||
CheckDefFailure(['let somevar'], "E1022:")
|
CheckDefFailure(['var somevar'], "E1022:")
|
||||||
CheckDefFailure(['let &tabstop = 4'], 'E1052:')
|
CheckDefFailure(['var &tabstop = 4'], 'E1052:')
|
||||||
CheckDefFailure(['&g:option = 5'], 'E113:')
|
CheckDefFailure(['&g:option = 5'], 'E113:')
|
||||||
CheckScriptFailure(['vim9script', 'let &tabstop = 4'], 'E1052:')
|
CheckScriptFailure(['vim9script', 'var &tabstop = 4'], 'E1052:')
|
||||||
|
|
||||||
CheckDefFailure(['let $VAR = 5'], 'E1016: Cannot declare an environment variable:')
|
CheckDefFailure(['var $VAR = 5'], 'E1016: Cannot declare an environment variable:')
|
||||||
CheckScriptFailure(['vim9script', 'let $ENV = "xxx"'], 'E1016:')
|
CheckScriptFailure(['vim9script', 'var $ENV = "xxx"'], 'E1016:')
|
||||||
|
|
||||||
if has('dnd')
|
if has('dnd')
|
||||||
CheckDefFailure(['let @~ = 5'], 'E1066:')
|
CheckDefFailure(['var @~ = 5'], 'E1066:')
|
||||||
else
|
else
|
||||||
CheckDefFailure(['let @~ = 5'], 'E354:')
|
CheckDefFailure(['var @~ = 5'], 'E354:')
|
||||||
CheckDefFailure(['@~ = 5'], 'E354:')
|
CheckDefFailure(['@~ = 5'], 'E354:')
|
||||||
endif
|
endif
|
||||||
CheckDefFailure(['let @a = 5'], 'E1066:')
|
CheckDefFailure(['var @a = 5'], 'E1066:')
|
||||||
CheckDefFailure(['let @/ = "x"'], 'E1066:')
|
CheckDefFailure(['var @/ = "x"'], 'E1066:')
|
||||||
CheckScriptFailure(['vim9script', 'let @a = "abc"'], 'E1066:')
|
CheckScriptFailure(['vim9script', 'var @a = "abc"'], 'E1066:')
|
||||||
|
|
||||||
CheckDefFailure(['let g:var = 5'], 'E1016: Cannot declare a global variable:')
|
CheckDefFailure(['var g:var = 5'], 'E1016: Cannot declare a global variable:')
|
||||||
CheckDefFailure(['let w:var = 5'], 'E1016: Cannot declare a window variable:')
|
CheckDefFailure(['var w:var = 5'], 'E1016: Cannot declare a window variable:')
|
||||||
CheckDefFailure(['let b:var = 5'], 'E1016: Cannot declare a buffer variable:')
|
CheckDefFailure(['var b:var = 5'], 'E1016: Cannot declare a buffer variable:')
|
||||||
CheckDefFailure(['let t:var = 5'], 'E1016: Cannot declare a tab variable:')
|
CheckDefFailure(['var t:var = 5'], 'E1016: Cannot declare a tab variable:')
|
||||||
|
|
||||||
CheckDefFailure(['let anr = 4', 'anr ..= "text"'], 'E1019:')
|
CheckDefFailure(['var anr = 4', 'anr ..= "text"'], 'E1019:')
|
||||||
CheckDefFailure(['let xnr += 4'], 'E1020:', 1)
|
CheckDefFailure(['var xnr += 4'], 'E1020:', 1)
|
||||||
CheckScriptFailure(['vim9script', 'let xnr += 4'], 'E1020:')
|
CheckScriptFailure(['vim9script', 'var xnr += 4'], 'E1020:')
|
||||||
CheckDefFailure(["let xnr = xnr + 1"], 'E1001:', 1)
|
CheckDefFailure(["var xnr = xnr + 1"], 'E1001:', 1)
|
||||||
CheckScriptFailure(['vim9script', 'let xnr = xnr + 4'], 'E121:')
|
CheckScriptFailure(['vim9script', 'var xnr = xnr + 4'], 'E121:')
|
||||||
|
|
||||||
CheckScriptFailure(['vim9script', 'def Func()', 'let dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
|
CheckScriptFailure(['vim9script', 'def Func()', 'var dummy = s:notfound', 'enddef', 'defcompile'], 'E1108:')
|
||||||
|
|
||||||
CheckDefFailure(['let var: list<string> = [123]'], 'expected list<string> but got list<number>')
|
CheckDefFailure(['var var: list<string> = [123]'], 'expected list<string> but got list<number>')
|
||||||
CheckDefFailure(['let var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
|
CheckDefFailure(['var var: list<number> = ["xx"]'], 'expected list<number> but got list<string>')
|
||||||
|
|
||||||
CheckDefFailure(['let var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
|
CheckDefFailure(['var var: dict<string> = #{key: 123}'], 'expected dict<string> but got dict<number>')
|
||||||
CheckDefFailure(['let var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
|
CheckDefFailure(['var var: dict<number> = #{key: "xx"}'], 'expected dict<number> but got dict<string>')
|
||||||
|
|
||||||
CheckDefFailure(['let var = feedkeys("0")'], 'E1031:')
|
CheckDefFailure(['var var = feedkeys("0")'], 'E1031:')
|
||||||
CheckDefFailure(['let var: number = feedkeys("0")'], 'expected number but got void')
|
CheckDefFailure(['var var: number = feedkeys("0")'], 'expected number but got void')
|
||||||
|
|
||||||
CheckDefFailure(['let var: dict <number>'], 'E1068:')
|
CheckDefFailure(['var var: dict <number>'], 'E1068:')
|
||||||
CheckDefFailure(['let var: dict<number'], 'E1009:')
|
CheckDefFailure(['var var: dict<number'], 'E1009:')
|
||||||
|
|
||||||
assert_fails('s/^/\=Mess()/n', 'E794:')
|
assert_fails('s/^/\=Mess()/n', 'E794:')
|
||||||
CheckDefFailure(['let var: dict<number'], 'E1009:')
|
CheckDefFailure(['var var: dict<number'], 'E1009:')
|
||||||
|
|
||||||
CheckDefFailure(['w:foo: number = 10'],
|
CheckDefFailure(['w:foo: number = 10'],
|
||||||
'E488: Trailing characters: : number = 1')
|
'E488: Trailing characters: : number = 1')
|
||||||
@ -657,7 +658,7 @@ def Test_assignment_failure()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assign_list()
|
def Test_assign_list()
|
||||||
let l: list<string> = []
|
var l: list<string> = []
|
||||||
l[0] = 'value'
|
l[0] = 'value'
|
||||||
assert_equal('value', l[0])
|
assert_equal('value', l[0])
|
||||||
|
|
||||||
@ -667,7 +668,7 @@ def Test_assign_list()
|
|||||||
assert_equal('asdf', l[-1])
|
assert_equal('asdf', l[-1])
|
||||||
assert_equal('value', l[-2])
|
assert_equal('value', l[-2])
|
||||||
|
|
||||||
let nrl: list<number> = []
|
var nrl: list<number> = []
|
||||||
for i in range(5)
|
for i in range(5)
|
||||||
nrl[i] = i
|
nrl[i] = i
|
||||||
endfor
|
endfor
|
||||||
@ -675,7 +676,7 @@ def Test_assign_list()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assign_dict()
|
def Test_assign_dict()
|
||||||
let d: dict<string> = {}
|
var d: dict<string> = {}
|
||||||
d['key'] = 'value'
|
d['key'] = 'value'
|
||||||
assert_equal('value', d['key'])
|
assert_equal('value', d['key'])
|
||||||
|
|
||||||
@ -683,7 +684,7 @@ def Test_assign_dict()
|
|||||||
assert_equal('qwerty', d[123])
|
assert_equal('qwerty', d[123])
|
||||||
assert_equal('qwerty', d['123'])
|
assert_equal('qwerty', d['123'])
|
||||||
|
|
||||||
let nrd: dict<number> = {}
|
var nrd: dict<number> = {}
|
||||||
for i in range(3)
|
for i in range(3)
|
||||||
nrd[i] = i
|
nrd[i] = i
|
||||||
endfor
|
endfor
|
||||||
@ -691,12 +692,12 @@ def Test_assign_dict()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_assign_dict_unknown_type()
|
def Test_assign_dict_unknown_type()
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let mylist = []
|
var mylist = []
|
||||||
mylist += [#{one: 'one'}]
|
mylist += [#{one: 'one'}]
|
||||||
def Func()
|
def Func()
|
||||||
let dd = mylist[0]
|
var dd = mylist[0]
|
||||||
assert_equal('one', dd.one)
|
assert_equal('one', dd.one)
|
||||||
enddef
|
enddef
|
||||||
Func()
|
Func()
|
||||||
@ -706,10 +707,10 @@ def Test_assign_dict_unknown_type()
|
|||||||
# doesn't work yet
|
# doesn't work yet
|
||||||
#lines =<< trim END
|
#lines =<< trim END
|
||||||
# vim9script
|
# vim9script
|
||||||
# let mylist = [[]]
|
# var mylist = [[]]
|
||||||
# mylist[0] += [#{one: 'one'}]
|
# mylist[0] += [#{one: 'one'}]
|
||||||
# def Func()
|
# def Func()
|
||||||
# let dd = mylist[0][0]
|
# var dd = mylist[0][0]
|
||||||
# assert_equal('one', dd.one)
|
# assert_equal('one', dd.one)
|
||||||
# enddef
|
# enddef
|
||||||
# Func()
|
# Func()
|
||||||
@ -719,13 +720,13 @@ enddef
|
|||||||
|
|
||||||
def Test_assign_lambda()
|
def Test_assign_lambda()
|
||||||
# check if assign a lambda to a variable which type is func or any.
|
# check if assign a lambda to a variable which type is func or any.
|
||||||
let lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
let FuncRef = {->123}
|
var FuncRef = {->123}
|
||||||
assert_equal(123, FuncRef())
|
assert_equal(123, FuncRef())
|
||||||
let FuncRef_Func: func = {->123}
|
var FuncRef_Func: func = {->123}
|
||||||
assert_equal(123, FuncRef_Func())
|
assert_equal(123, FuncRef_Func())
|
||||||
let FuncRef_Any: any = {->123}
|
var FuncRef_Any: any = {->123}
|
||||||
assert_equal(123, FuncRef_Any())
|
assert_equal(123, FuncRef_Any())
|
||||||
END
|
END
|
||||||
CheckScriptSuccess(lines)
|
CheckScriptSuccess(lines)
|
||||||
|
@ -193,21 +193,21 @@ def Test_wrong_type()
|
|||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_const()
|
def Test_const()
|
||||||
CheckDefFailure(['const var = 234', 'var = 99'], 'E1018:')
|
CheckDefFailure(['final var = 234', 'var = 99'], 'E1018:')
|
||||||
CheckDefFailure(['const one = 234', 'let one = 99'], 'E1017:')
|
CheckDefFailure(['final one = 234', 'let one = 99'], 'E1017:')
|
||||||
CheckDefFailure(['const list = [1, 2]', 'let list = [3, 4]'], 'E1017:')
|
CheckDefFailure(['final list = [1, 2]', 'let list = [3, 4]'], 'E1017:')
|
||||||
CheckDefFailure(['const two'], 'E1021:')
|
CheckDefFailure(['final two'], 'E1125:')
|
||||||
CheckDefFailure(['const &option'], 'E996:')
|
CheckDefFailure(['final &option'], 'E996:')
|
||||||
|
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
const list = [1, 2, 3]
|
final list = [1, 2, 3]
|
||||||
list[0] = 4
|
list[0] = 4
|
||||||
list->assert_equal([4, 2, 3])
|
list->assert_equal([4, 2, 3])
|
||||||
const! other = [5, 6, 7]
|
const other = [5, 6, 7]
|
||||||
other->assert_equal([5, 6, 7])
|
other->assert_equal([5, 6, 7])
|
||||||
|
|
||||||
let varlist = [7, 8]
|
let varlist = [7, 8]
|
||||||
const! constlist = [1, varlist, 3]
|
const constlist = [1, varlist, 3]
|
||||||
varlist[0] = 77
|
varlist[0] = 77
|
||||||
# TODO: does not work yet
|
# TODO: does not work yet
|
||||||
# constlist[1][1] = 88
|
# constlist[1][1] = 88
|
||||||
@ -216,7 +216,7 @@ def Test_const()
|
|||||||
constlist->assert_equal([1, [77, 88], 3])
|
constlist->assert_equal([1, [77, 88], 3])
|
||||||
|
|
||||||
let vardict = #{five: 5, six: 6}
|
let vardict = #{five: 5, six: 6}
|
||||||
const! constdict = #{one: 1, two: vardict, three: 3}
|
const constdict = #{one: 1, two: vardict, three: 3}
|
||||||
vardict['five'] = 55
|
vardict['five'] = 55
|
||||||
# TODO: does not work yet
|
# TODO: does not work yet
|
||||||
# constdict['two']['six'] = 66
|
# constdict['two']['six'] = 66
|
||||||
@ -229,35 +229,35 @@ enddef
|
|||||||
|
|
||||||
def Test_const_bang()
|
def Test_const_bang()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
const! var = 234
|
const var = 234
|
||||||
var = 99
|
var = 99
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1018:', 2)
|
CheckDefExecFailure(lines, 'E1018:', 2)
|
||||||
CheckScriptFailure(['vim9script'] + lines, 'E46:', 3)
|
CheckScriptFailure(['vim9script'] + lines, 'E46:', 3)
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
const! ll = [2, 3, 4]
|
const ll = [2, 3, 4]
|
||||||
ll[0] = 99
|
ll[0] = 99
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1119:', 2)
|
CheckDefExecFailure(lines, 'E1119:', 2)
|
||||||
CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
|
CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
const! ll = [2, 3, 4]
|
const ll = [2, 3, 4]
|
||||||
ll[3] = 99
|
ll[3] = 99
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1118:', 2)
|
CheckDefExecFailure(lines, 'E1118:', 2)
|
||||||
CheckScriptFailure(['vim9script'] + lines, 'E684:', 3)
|
CheckScriptFailure(['vim9script'] + lines, 'E684:', 3)
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
const! dd = #{one: 1, two: 2}
|
const dd = #{one: 1, two: 2}
|
||||||
dd["one"] = 99
|
dd["one"] = 99
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1121:', 2)
|
CheckDefExecFailure(lines, 'E1121:', 2)
|
||||||
CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
|
CheckScriptFailure(['vim9script'] + lines, 'E741:', 3)
|
||||||
|
|
||||||
lines =<< trim END
|
lines =<< trim END
|
||||||
const! dd = #{one: 1, two: 2}
|
const dd = #{one: 1, two: 2}
|
||||||
dd["three"] = 99
|
dd["three"] = 99
|
||||||
END
|
END
|
||||||
CheckDefExecFailure(lines, 'E1120:')
|
CheckDefExecFailure(lines, 'E1120:')
|
||||||
@ -2531,6 +2531,12 @@ enddef
|
|||||||
|
|
||||||
def Test_let_declaration_fails()
|
def Test_let_declaration_fails()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
final var: string
|
||||||
|
END
|
||||||
|
CheckScriptFailure(lines, 'E1125:')
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
const var: string
|
const var: string
|
||||||
END
|
END
|
||||||
|
@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1744,
|
||||||
/**/
|
/**/
|
||||||
1743,
|
1743,
|
||||||
/**/
|
/**/
|
||||||
|
@ -2135,9 +2135,9 @@ typedef enum {
|
|||||||
} estack_arg_T;
|
} estack_arg_T;
|
||||||
|
|
||||||
// Flags for assignment functions.
|
// Flags for assignment functions.
|
||||||
#define LET_IS_CONST 1 // ":const"
|
#define ASSIGN_FINAL 1 // ":final"
|
||||||
#define LET_FORCEIT 2 // ":const!" (LET_IS_CONST is also set)
|
#define ASSIGN_CONST 2 // ":const"
|
||||||
#define LET_NO_COMMAND 4 // "var = expr" without ":let" or ":const"
|
#define ASSIGN_NO_DECL 4 // "name = expr" without ":let" or ":const"
|
||||||
|
|
||||||
#include "ex_cmds.h" // Ex command defines
|
#include "ex_cmds.h" // Ex command defines
|
||||||
#include "spell.h" // spell checking stuff
|
#include "spell.h" // spell checking stuff
|
||||||
|
@ -4562,8 +4562,12 @@ vim9_declare_error(char_u *name)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Compile declaration and assignment:
|
* Compile declaration and assignment:
|
||||||
* "let var", "let var = expr", "const var = expr" and "var = expr"
|
* "let name"
|
||||||
* "arg" points to "var".
|
* "var name = expr"
|
||||||
|
* "final name = expr"
|
||||||
|
* "const name = expr"
|
||||||
|
* "name = expr"
|
||||||
|
* "arg" points to "name".
|
||||||
* Return NULL for an error.
|
* Return NULL for an error.
|
||||||
* Return "arg" if it does not look like a variable list.
|
* Return "arg" if it does not look like a variable list.
|
||||||
*/
|
*/
|
||||||
@ -4588,7 +4592,8 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
type_T *member_type = &t_any;
|
type_T *member_type = &t_any;
|
||||||
char_u *name = NULL;
|
char_u *name = NULL;
|
||||||
char_u *sp;
|
char_u *sp;
|
||||||
int is_decl = cmdidx == CMD_let || cmdidx == CMD_const;
|
int is_decl = cmdidx == CMD_let || cmdidx == CMD_var
|
||||||
|
|| cmdidx == CMD_final || cmdidx == CMD_const;
|
||||||
|
|
||||||
// Skip over the "var" or "[var, var]" to get to any "=".
|
// Skip over the "var" or "[var, var]" to get to any "=".
|
||||||
p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
|
p = skip_var_list(arg, TRUE, &var_count, &semicolon, TRUE);
|
||||||
@ -4729,7 +4734,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
long numval;
|
long numval;
|
||||||
|
|
||||||
dest = dest_option;
|
dest = dest_option;
|
||||||
if (cmdidx == CMD_const)
|
if (cmdidx == CMD_final || cmdidx == CMD_const)
|
||||||
{
|
{
|
||||||
emsg(_(e_const_option));
|
emsg(_(e_const_option));
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -4968,7 +4973,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
&& var_wrong_func_name(name, TRUE))
|
&& var_wrong_func_name(name, TRUE))
|
||||||
goto theend;
|
goto theend;
|
||||||
lvar = reserve_local(cctx, var_start, varlen,
|
lvar = reserve_local(cctx, var_start, varlen,
|
||||||
cmdidx == CMD_const, type);
|
cmdidx == CMD_final || cmdidx == CMD_const, type);
|
||||||
if (lvar == NULL)
|
if (lvar == NULL)
|
||||||
goto theend;
|
goto theend;
|
||||||
new_local = TRUE;
|
new_local = TRUE;
|
||||||
@ -5119,6 +5124,11 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
cctx, FALSE) == FAIL)
|
cctx, FALSE) == FAIL)
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
else if (cmdidx == CMD_final)
|
||||||
|
{
|
||||||
|
emsg(_(e_final_requires_a_value));
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
else if (cmdidx == CMD_const)
|
else if (cmdidx == CMD_const)
|
||||||
{
|
{
|
||||||
emsg(_(e_const_requires_a_value));
|
emsg(_(e_const_requires_a_value));
|
||||||
@ -5283,9 +5293,9 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (is_decl && eap->forceit && cmdidx == CMD_const
|
if (is_decl && cmdidx == CMD_const
|
||||||
&& (dest == dest_script || dest == dest_local))
|
&& (dest == dest_script || dest == dest_local))
|
||||||
// ":const! var": lock the value, but not referenced variables
|
// ":const var": lock the value, but not referenced variables
|
||||||
generate_LOCKCONST(cctx);
|
generate_LOCKCONST(cctx);
|
||||||
|
|
||||||
switch (dest)
|
switch (dest)
|
||||||
@ -6915,7 +6925,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
|||||||
// Expression or function call.
|
// Expression or function call.
|
||||||
if (ea.cmdidx != CMD_eval)
|
if (ea.cmdidx != CMD_eval)
|
||||||
{
|
{
|
||||||
// CMD_let cannot happen, compile_assignment() above is used
|
// CMD_var cannot happen, compile_assignment() above is used
|
||||||
iemsg("Command from find_ex_command() not handled");
|
iemsg("Command from find_ex_command() not handled");
|
||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
@ -6967,6 +6977,8 @@ compile_def_function(ufunc_T *ufunc, int set_return_type, cctx_T *outer_cctx)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_let:
|
case CMD_let:
|
||||||
|
case CMD_var:
|
||||||
|
case CMD_final:
|
||||||
case CMD_const:
|
case CMD_const:
|
||||||
line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
|
line = compile_assignment(p, &ea, ea.cmdidx, &cctx);
|
||||||
if (line == p)
|
if (line == p)
|
||||||
|
@ -729,7 +729,7 @@ store_var(char_u *name, typval_T *tv)
|
|||||||
funccal_entry_T entry;
|
funccal_entry_T entry;
|
||||||
|
|
||||||
save_funccal(&entry);
|
save_funccal(&entry);
|
||||||
set_var_const(name, NULL, tv, FALSE, LET_NO_COMMAND);
|
set_var_const(name, NULL, tv, FALSE, ASSIGN_NO_DECL);
|
||||||
restore_funccal();
|
restore_funccal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ ex_export(exarg_T *eap)
|
|||||||
switch (eap->cmdidx)
|
switch (eap->cmdidx)
|
||||||
{
|
{
|
||||||
case CMD_let:
|
case CMD_let:
|
||||||
|
case CMD_var:
|
||||||
|
case CMD_final:
|
||||||
case CMD_const:
|
case CMD_const:
|
||||||
case CMD_def:
|
case CMD_def:
|
||||||
// case CMD_class:
|
// case CMD_class:
|
||||||
@ -508,8 +510,11 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg)
|
|||||||
int called_emsg_before = called_emsg;
|
int called_emsg_before = called_emsg;
|
||||||
typval_T init_tv;
|
typval_T init_tv;
|
||||||
|
|
||||||
if (eap->cmdidx == CMD_const)
|
if (eap->cmdidx == CMD_final || eap->cmdidx == CMD_const)
|
||||||
{
|
{
|
||||||
|
if (eap->cmdidx == CMD_final)
|
||||||
|
emsg(_(e_final_requires_a_value));
|
||||||
|
else
|
||||||
emsg(_(e_const_requires_a_value));
|
emsg(_(e_const_requires_a_value));
|
||||||
return arg + STRLEN(arg);
|
return arg + STRLEN(arg);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user