Proposal: scriptstrict directive (Do Not Merge)#3857
Proposal: scriptstrict directive (Do Not Merge)#3857mattn wants to merge 3 commits intovim:masterfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## master #3857 +/- ##
==========================================
- Coverage 78.66% 78.64% -0.02%
==========================================
Files 103 103
Lines 141899 141912 +13
==========================================
- Hits 111618 111608 -10
- Misses 30281 30304 +23
Continue to review full report at Codecov.
|
|
Yasuhiro Matsumoto wrote:
I propose to add new directive command `scriptstrict` to indicate that
the code should be executed in "strict mode".
# Background
In the specification of Vim script, Vim script allow to put `.` for
two expression.
1. concating two string values
2. reference item of dictionary
### code1
```vim
let a = 'a'
let b = 'b'
echo a.b
```
### code2
```vim
let a = {'b': 'c'}
echo a.b
```
S expression (pseudo) of code1 is:
```lisp
(progn
(let = a 'a')
(let = b 'b')
(echo (concat a b))
)
```
And code2 is:
```lisp
(progn
(let a (dict ('b' 'c'))
(echo (gethash 'b' a))
)
```
So Vim script is not possible to generate AST (Abstruct Syntaxx Tree).
To make Vim script faster, we should compile Vim script to AST, and
make AST walker. However, the meaning of `.` operator is indefinite
until the type of left-side express is recognized.
# Proposal
I suggest that the operator for the concat strings is obsolete.
However, Vim place too much compatibilities. So I added `scriptstrict`
directive. This works as Ex command like `scriptencoding`. When put
`scriptstrict` in your Vim script, Vim does not allow expression `a.b`
to be interpret as concat strings. If you want to do it, the
expression must be `a .b` or `a . b`. This pull-request is not ready
to merge since I thought we have to discuss. But if you build this
pull-request, Following Vim script works as well.
```vim
" Concating strings: This is OK since not strict mode
let a = 'a'
let b = 'b'
echo a.b
" Reference item in dictionary: This is OK since not strict mode
let a = {'b': 'b'}
echo a.b
" Then, scriptstrict flag on.
scriptstrict
" Concating strings: This is NG since strict mode
let a = 'a'
let b = 'b'
try
echo a.b
catch
echohl ErrorMsg | echo 'Do not use "." for concating strings!' | echohl None
endtry
" Concating strings but include space before dot: This is OK
let a = 'a'
let b = 'b'
echo a .b
" Reference item in dictionary: This is OK even when strict mode
let a = {'b': 'b'}
echo a.b
```
Please note that I don't say that Vim script is possible to implement
AST parser if the `a.b` will be removed. This is one of candidate that
have to be removed.
I would like to hear your opinions. Thanks.
I like the general idea, but I think we should do more.
Here we look into string concatenation, and change a small part of how
the Vim script syntax and semantics are defined. I'm sure that in the
future we would want to make more changes.
Instead of using "scriptstrict" we could use "scriptversion", which
would give the version of Vim script that the file uses. This follows
the "scriptencoding" command which specifies the encoding of the file.
Most likely "scriptversion" can just have a number argument, which will
increase over time when we make improvements. That means a script at
version 5 must also include all the changes made in versions 1 to 4.
An alternative would be to specify a list of specific script changes.
But that quickly becomes hard to use and makes it difficult to read and
understand a script written by someone else.
For string concatenation, instead of using the confusing "." operator, I
would prefer to use "..". I have done this in Zimbu and it works well.
It also avoids the confusion of using "+" to concatenate strings,
because of the automatic conversion of a string with a number to a
number:
echo '3' + 4
7
In Javascript the result would be "34". To avoid confusion, we could
disallow using a string with the "+" operator, or in general disallow
the automatic string to number conversion.
We could collect a few of these small but confusing issues with Vim
script and call that "scriptversion 2".
echo 'a' .. 'b'
ab
echo '3' .. 4
Error: using number as a string
echo 3.4
3.4
echo .5
0.5
echo 3 .4
3 0.4
echo 3 . 4
Error: "." operator not supported in scriptversion 2
I would also like to enforce some spacing for readability:
let alpha=beta+gamma
Error: must use spaces around assignment in scriptversion 2
let alpha = beta + gamma
…--
Eight Megabytes And Continually Swapping.
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
|
Yes, I also thought that let a = "a"
let b = "b"
let c = "c"
let x = a.b.cThis mean: (let = x (concat a b c))But let a = {"b": {"c"}}
let x = a.b.cThis mean: (let = x (gethash 'c' (gethash 'b' a)) |
|
I don't see what's wrong with "." for string concatenation (still less why it would be "obsolete"). It seems to me that it's the dictionary notation that should be changed. |
|
No. Vim script have dictionary function. And many plugins have the codes. |
|
Vim script also has a string concatenation operator. And many plugins and scripts use it. |
|
What do you worry about? I'm not trying to completely delete string concatings. If you want to use string concatings with "a.b", you can use if you don't put "scriptversion". This is only thing that scripts are not optimized in future. |
|
I worry that no reason has been given for taking "." away from string concatenation (in "strict mode") instead of taking "." away from dictionary expressions. Why not just require (in "strict mode") the dictionary expression |
|
@chdiza Dictionary expressions have always been written as I concur with Bram that such endeavor should be part of a larger redesign. If this is done piecemeal through many minor revisions, and without discernible (performance) benefits, I doubt this will get much traction. Why should a plugin writer make changes that break backwards compatibility if there's a chance this soon needs to be adapted again? Also, this probably won't silence those critics that dislike Vimscript in general (unless this gets a complete, radical overhaul, and then shouldn't be called Vimscript any longer). I wonder if we couldn't just leverage any performance optimizations from other scripting languages: If, say, Python does a great job there already, why not just invest some time in better and efficient Vim bindings, and then tell plugin writers to implement large plugins in Python? |
Haven't they also always been written as |
|
Dictionary expression certainly can be written |
|
@chdiza In |
|
I worry that no reason has been given for taking "." away from string
concatenation (in "strict mode") instead of taking "." away from
dictionary expressions. Why not just require (in "strict mode") the
dictionary expression `a.b` to instead be `a[b]`?
For most users Vim script is not their main language. Thus it's best if
Vim does something that users expect from other languages.
Most languages use "." for membership, thus it's best we follow that.
It includes Javascript, Java and even C (if you consider a struct member
to be similar to a dict member).
For string concatenation there isn't such a common syntax. Most
language use "+", but it's easily confused with adding numbers. I
regularly see mistakes in the use of "+" because of overloading it.
Some languages, such as Perl and PHP do use ".".
Lua uses ".." and I followed that in Zimbu. It turns out this works
very well, makes the expressions easier to read and avoids mistakes.
For example, if you see:
c = a .. b
You immediately know it's a string concatenation, while with:
c = a + b
you need to lookup types to know what it's doing. It's not a strong
argument, since "+" is also used for list concatenation.
In Vim we have an additional quirk in automatic converting a string with
a number to a number. So that if you get a number from a line of text
it works without conversion. Might have been a bad idea, but it's hard
to get rid of now and it would lead to very subtle mistakes.
Some languages do it exactly the other way around: Adding a number to a
string with "+" converts the number to a string before the
concatenation. This can be nice, avoiding an explicit toString(), but
it can also lead to mistakes. Using the operator "..", which is
unambiguously for string concatenation, avoids these problems.
Automatic conversion to string won't be confusing then.
…--
** Hello and Welcome to the Psychiatric Hotline **
If you are obsessive-compulsive, please press 1 repeatedly.
If you are co-dependent, please ask someone to press 2.
If you have multiple personalities, please press 3, 4, 5 and 6.
If you are paranoid-delusional, we know who you are and what you want
- just stay on the line so we can trace the call.
If you are schizophrenic, listen carefully and a little voice will
tell you which number to press next.
If you are manic-depressive, it doesn't matter which number you press
- no one will answer.
If you suffer from panic attacks, push every button you can find.
If you are sane, please hold on - we have the rest of humanity on the
other line and they desparately want to ask you a few questions.
/// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
|
Vim will need to keep "a[b]" anyway, because otherwise there's no way to distinguish between "a.b" where a is a dictionary and "b" is one of its string keys, and "a.b" where a is a dictionary and b is a variable whose value is one of a's keys. That will produce 1, so to get 3 via the variable b one will need to do |
|
As mentioned in above, Vim script have dictionary function. let a = {"value": 1}
function! a.b(k)
echo self[a:k]
endfunction
call a.b("value")Many Vim plugins are using this idiom. |
|
And many script author is using spaces arround |
|
I want to suggest one more thing to be avoided confusing. function! s:test()
let l:l = 1
let l:k = 2
let l:c = [1,2,3]
echo l:c[l:l:k]
endfunction
call s:test()This is parsed as: echo l:c[l:l: k]But can be confused to: echo l:c[l :l:k]In strict mode, spaces arround echo l:c[l:l : k] |
|
Any reason to leave out |
|
We don't mean that we will remove |
|
@Houl is just saying to allow By the way, can such a directive (or a different name) have the effect of: |
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513 and vim/vim@68e6560.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a Include latest eval.txt changes for scriptversion-2 from v8.1.1513, vim/vim@68e6560 and vim/vim@911ead1. Include latest repeat.txt changes for :scriptversion from vim/vim@62e1bb4.
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a :scriptversion is N/A, but ":let ..=" is relevant. N/A patches for version.c vim-patch:8.1.1188: not all Vim variables require the v: prefix Problem: Not all Vim variables require the v: prefix. Solution: When scriptversion is 3 all Vim variables can only be used with the v: prefix. (Ken Takata, closes vim/vim#4274) vim/vim@d2e716e vim-patch:8.1.1190: has('vimscript-3') does not work Problem: has('vimscript-3') does not work. Solution: Add "vimscript-3" to the list of features. vim/vim@93a4879 vim-patch:8.1.2038: has('vimscript-4') is always 0 Problem: has('vimscript-4') is always 0. Solution: Add "vimscript-4" to the feature table. (Naruhiko Nishino, closes vim/vim#4941) vim/vim@af91438 vim-patch:8.1.2043: not sufficient testing for quoted numbers Problem: Not sufficient testing for quoted numbers. Solution: Add a few more test cases. vim/vim@ea8dcf8
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a :scriptversion is N/A, but ":let ..=" is relevant. N/A patches for version.c vim-patch:8.1.1188: not all Vim variables require the v: prefix Problem: Not all Vim variables require the v: prefix. Solution: When scriptversion is 3 all Vim variables can only be used with the v: prefix. (Ken Takata, closes vim/vim#4274) vim/vim@d2e716e vim-patch:8.1.1190: has('vimscript-3') does not work Problem: has('vimscript-3') does not work. Solution: Add "vimscript-3" to the list of features. vim/vim@93a4879 vim-patch:8.1.2038: has('vimscript-4') is always 0 Problem: has('vimscript-4') is always 0. Solution: Add "vimscript-4" to the feature table. (Naruhiko Nishino, closes vim/vim#4941) vim/vim@af91438
Problem: Cannot enforce a Vim script style. Solution: Add the :scriptversion command. (closes vim/vim#3857) vim/vim@558ca4a :scriptversion is N/A, but ":let ..=" is relevant. N/A patches for version.c vim-patch:8.1.1188: not all Vim variables require the v: prefix Problem: Not all Vim variables require the v: prefix. Solution: When scriptversion is 3 all Vim variables can only be used with the v: prefix. (Ken Takata, closes vim/vim#4274) vim/vim@d2e716e vim-patch:8.1.1190: has('vimscript-3') does not work Problem: has('vimscript-3') does not work. Solution: Add "vimscript-3" to the list of features. vim/vim@93a4879 vim-patch:8.1.2038: has('vimscript-4') is always 0 Problem: has('vimscript-4') is always 0. Solution: Add "vimscript-4" to the feature table. (Naruhiko Nishino, closes vim/vim#4941) vim/vim@af91438
I propose to add new directive command
scriptstrictto indicate that the code should be executed in "strict mode".Background
In the specification of Vim script, Vim script allow to put
.for two expression.code1
code2
S expression (pseudo) of code1 is:
And code2 is:
So Vim script is not possible to generate AST (Abstruct Syntax Tree) since
a.bcan not be parsed to the node of tree. To make Vim script faster, we should compile Vim script to AST, and make AST walker. However, the meaning of.operator is indefinite until the type of left-side express is recognized.Proposal
I suggest that the operator for the concat strings using
a.bis obsolete. However, Vim place too much compatibilities. So I addedscriptstrictdirective. This works as Ex command likescriptencoding. When putscriptstrictin your Vim script, Vim does not allow expressiona.bto be interpret as concat strings. If you want to do it, the expression must bea .bora . b. This pull-request is not ready to merge since I thought we have to discuss. But if you build this pull-request, Following Vim script works as well.Please note that I don't say that Vim script is possible to implement AST parser if the
a.bwill be removed. This is one of candidate that have to be removed.I would like to hear your opinions. Thanks.