Compare commits

...

3 Commits

Author SHA1 Message Date
Bram Moolenaar
1b1df95f1a patch 8.2.4540: line number for error is off by one
Problem:    Line number for error is off by one.
Solution:   Remember the line number of the comparison. (closes #9923)
2022-03-10 20:01:50 +00:00
Bram Moolenaar
53ba6ca5b2 patch 8.2.4539: when comparing special v:none and v:null are handled the same
Problem:    When comparing special v:none and v:null are handled the same when
            compiling.
Solution:   Pass more information so that v:none can be handled differently at
            compile time.  (issue #9923)
2022-03-10 19:23:28 +00:00
Yegappan Lakshmanan
bf40e90dfe patch 8.2.4538: the find_tags_in_file() function is too long
Problem:    The find_tags_in_file() function is too long.
Solution:   Refactor into smaller functions. (Yegappan Lakshmanan,
            closes #9920)
2022-03-10 18:36:54 +00:00
8 changed files with 835 additions and 669 deletions

View File

@@ -2849,6 +2849,7 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
int vim9script = in_vim9script();
int evaluate = evalarg == NULL
? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
long comp_lnum = SOURCING_LNUM;
if (getnext)
{
@@ -2904,6 +2905,8 @@ eval4(char_u **arg, typval_T *rettv, evalarg_T *evalarg)
{
int ret;
// use the line of the comparison for messages
SOURCING_LNUM = comp_lnum;
if (vim9script && check_compare_types(type, rettv, &var2) == FAIL)
{
ret = FAIL;

View File

@@ -398,7 +398,8 @@ EXTERN type_T t_any INIT6(VAR_ANY, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_void INIT6(VAR_VOID, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_bool INIT6(VAR_BOOL, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_special INIT6(VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_null INIT6(VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_none INIT6(VAR_SPECIAL, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_number INIT6(VAR_NUMBER, 0, 0, TTFLAG_STATIC, NULL, NULL);
EXTERN type_T t_number_bool INIT6(VAR_NUMBER, 0, 0, TTFLAG_STATIC|TTFLAG_BOOL_OK, NULL, NULL);
EXTERN type_T t_float INIT6(VAR_FLOAT, 0, 0, TTFLAG_STATIC, NULL, NULL);

1373
src/tag.c

File diff suppressed because it is too large Load Diff

View File

@@ -811,11 +811,11 @@ endfunc
" Test for an unsorted tags file
func Test_tag_sort()
call writefile([
let l = [
\ "first\tXfoo\t1",
\ "ten\tXfoo\t3",
\ "six\tXfoo\t2"],
\ 'Xtags')
\ "six\tXfoo\t2"]
call writefile(l, 'Xtags')
set tags=Xtags
let code =<< trim [CODE]
int first() {}
@@ -826,7 +826,14 @@ func Test_tag_sort()
call assert_fails('tag first', 'E432:')
" When multiple tag files are not sorted, then message should be displayed
" multiple times
call writefile(l, 'Xtags2')
set tags=Xtags,Xtags2
call assert_fails('tag first', ['E432:', 'E432:'])
call delete('Xtags')
call delete('Xtags2')
call delete('Xfoo')
set tags&
%bwipe

View File

@@ -828,8 +828,29 @@ def Test_expr4_compare_null()
v9.CheckDefAndScriptFailure(['echo true != v:null'], 'E1072: Cannot compare bool with special')
v9.CheckDefAndScriptFailure(['echo v:null != true'], 'E1072: Cannot compare special with bool')
v9.CheckDefAndScriptFailure(['echo false == v:null'], 'E1072: Cannot compare bool with special')
enddef
v9.CheckDefExecAndScriptFailure(['echo [] == v:none'], ['E1072: Cannot compare list with special', 'E691: Can only compare List with List'])
def Test_expr4_compare_none()
var lines =<< trim END
assert_false('' == v:none)
assert_false('text' == v:none)
assert_true(v:none == v:none)
assert_false(v:none == '')
assert_false(v:none == 'text')
assert_true(v:none == v:none)
END
v9.CheckDefAndScriptSuccess(lines)
v9.CheckDefAndScriptFailure(['echo [] == v:none'], 'E1072: Cannot compare list with special')
v9.CheckDefAndScriptFailure(['echo 123 == v:none'], 'E1072: Cannot compare number with special')
v9.CheckDefAndScriptFailure(['echo 0z00 == v:none'], 'E1072: Cannot compare blob with special')
lines =<< trim END
echo [] == v:none
eval 0 + 0
END
v9.CheckDefAndScriptFailure(lines, 'E1072:', 1)
enddef
def Test_expr4_wrong_type()

View File

@@ -750,6 +750,12 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4540,
/**/
4539,
/**/
4538,
/**/
4537,
/**/

View File

@@ -1799,7 +1799,7 @@ compile_assign_unlet(
return FAIL;
}
type = get_type_on_stack(cctx, 0);
if ((dest_type != VAR_BLOB && type != &t_special)
if ((dest_type != VAR_BLOB && type->tt_type != VAR_SPECIAL)
&& need_type(type, &t_number,
-1, 0, cctx, FALSE, FALSE) == FAIL)
return FAIL;

View File

@@ -339,22 +339,30 @@ generate_two_op(cctx_T *cctx, char_u *op)
}
/*
* Get the instruction to use for comparing "type1" with "type2"
* Get the instruction to use for comparing two values with specified types.
* Either "tv1" and "tv2" are passed or "type1" and "type2".
* Return ISN_DROP when failed.
*/
static isntype_T
get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
get_compare_isn(
exprtype_T exprtype,
typval_T *tv1,
typval_T *tv2,
type_T *type1,
type_T *type2)
{
isntype_T isntype = ISN_DROP;
vartype_T vartype1 = tv1 != NULL ? tv1->v_type : type1->tt_type;
vartype_T vartype2 = tv2 != NULL ? tv2->v_type : type2->tt_type;
if (type1 == VAR_UNKNOWN)
type1 = VAR_ANY;
if (type2 == VAR_UNKNOWN)
type2 = VAR_ANY;
if (vartype1 == VAR_UNKNOWN)
vartype1 = VAR_ANY;
if (vartype2 == VAR_UNKNOWN)
vartype2 = VAR_ANY;
if (type1 == type2)
if (vartype1 == vartype2)
{
switch (type1)
switch (vartype1)
{
case VAR_BOOL: isntype = ISN_COMPAREBOOL; break;
case VAR_SPECIAL: isntype = ISN_COMPARESPECIAL; break;
@@ -368,15 +376,28 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
default: isntype = ISN_COMPAREANY; break;
}
}
else if (type1 == VAR_ANY || type2 == VAR_ANY
|| ((type1 == VAR_NUMBER || type1 == VAR_FLOAT)
&& (type2 == VAR_NUMBER || type2 == VAR_FLOAT))
|| (type1 == VAR_FUNC && type2 == VAR_PARTIAL)
|| (type1 == VAR_PARTIAL && type2 == VAR_FUNC))
else if (vartype1 == VAR_ANY || vartype2 == VAR_ANY
|| ((vartype1 == VAR_NUMBER || vartype1 == VAR_FLOAT)
&& (vartype2 == VAR_NUMBER || vartype2 == VAR_FLOAT))
|| (vartype1 == VAR_FUNC && vartype2 == VAR_PARTIAL)
|| (vartype1 == VAR_PARTIAL && vartype2 == VAR_FUNC))
isntype = ISN_COMPAREANY;
else if (type1 == VAR_SPECIAL || type2 == VAR_SPECIAL)
else if (vartype1 == VAR_SPECIAL || vartype2 == VAR_SPECIAL)
{
switch (type1 == VAR_SPECIAL ? type2 : type1)
if ((vartype1 == VAR_SPECIAL
&& (tv1 != NULL ? tv1->vval.v_number == VVAL_NONE
: type1 == &t_none)
&& vartype2 != VAR_STRING)
|| (vartype2 == VAR_SPECIAL
&& (tv2 != NULL ? tv2->vval.v_number == VVAL_NONE
: type2 == &t_none)
&& vartype1 != VAR_STRING))
{
semsg(_(e_cannot_compare_str_with_str),
vartype_name(vartype1), vartype_name(vartype2));
return ISN_DROP;
}
switch (vartype1 == VAR_SPECIAL ? vartype2 : vartype1)
{
case VAR_BLOB: break;
case VAR_CHANNEL: break;
@@ -387,7 +408,7 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
case VAR_PARTIAL: break;
case VAR_STRING: break;
default: semsg(_(e_cannot_compare_str_with_str),
vartype_name(type1), vartype_name(type2));
vartype_name(vartype1), vartype_name(vartype2));
return ISN_DROP;
}
isntype = ISN_COMPARENULL;
@@ -400,20 +421,20 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
|| isntype == ISN_COMPAREFLOAT))
{
semsg(_(e_cannot_use_str_with_str),
exprtype == EXPR_IS ? "is" : "isnot" , vartype_name(type1));
exprtype == EXPR_IS ? "is" : "isnot" , vartype_name(vartype1));
return ISN_DROP;
}
if (isntype == ISN_DROP
|| ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
&& (type1 == VAR_BOOL || type1 == VAR_SPECIAL
|| type2 == VAR_BOOL || type2 == VAR_SPECIAL)))
&& (vartype1 == VAR_BOOL || vartype1 == VAR_SPECIAL
|| vartype2 == VAR_BOOL || vartype2 == VAR_SPECIAL)))
|| ((exprtype != EXPR_EQUAL && exprtype != EXPR_NEQUAL
&& exprtype != EXPR_IS && exprtype != EXPR_ISNOT
&& (type1 == VAR_BLOB || type2 == VAR_BLOB
|| type1 == VAR_LIST || type2 == VAR_LIST))))
&& (vartype1 == VAR_BLOB || vartype2 == VAR_BLOB
|| vartype1 == VAR_LIST || vartype2 == VAR_LIST))))
{
semsg(_(e_cannot_compare_str_with_str),
vartype_name(type1), vartype_name(type2));
vartype_name(vartype1), vartype_name(vartype2));
return ISN_DROP;
}
return isntype;
@@ -422,7 +443,7 @@ get_compare_isn(exprtype_T exprtype, vartype_T type1, vartype_T type2)
int
check_compare_types(exprtype_T type, typval_T *tv1, typval_T *tv2)
{
if (get_compare_isn(type, tv1->v_type, tv2->v_type) == ISN_DROP)
if (get_compare_isn(type, tv1, tv2, NULL, NULL) == ISN_DROP)
return FAIL;
return OK;
}
@@ -436,17 +457,14 @@ generate_COMPARE(cctx_T *cctx, exprtype_T exprtype, int ic)
isntype_T isntype;
isn_T *isn;
garray_T *stack = &cctx->ctx_type_stack;
vartype_T type1;
vartype_T type2;
RETURN_OK_IF_SKIP(cctx);
// Get the known type of the two items on the stack. If they are matching
// use a type-specific instruction. Otherwise fall back to runtime type
// checking.
type1 = get_type_on_stack(cctx, 1)->tt_type;
type2 = get_type_on_stack(cctx, 0)->tt_type;
isntype = get_compare_isn(exprtype, type1, type2);
isntype = get_compare_isn(exprtype, NULL, NULL,
get_type_on_stack(cctx, 1), get_type_on_stack(cctx, 0));
if (isntype == ISN_DROP)
return FAIL;
@@ -664,7 +682,8 @@ generate_PUSHSPEC(cctx_T *cctx, varnumber_T number)
isn_T *isn;
RETURN_OK_IF_SKIP(cctx);
if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC, &t_special)) == NULL)
if ((isn = generate_instr_type(cctx, ISN_PUSHSPEC,
number == VVAL_NULL ? &t_null : &t_none)) == NULL)
return FAIL;
isn->isn_arg.number = number;
@@ -1475,7 +1494,7 @@ generate_CALL(cctx_T *cctx, ufunc_T *ufunc, int pushed_argcount)
type_T *actual;
actual = get_type_on_stack(cctx, argcount - i - 1);
if (actual == &t_special
if (actual->tt_type == VAR_SPECIAL
&& i >= regular_args - ufunc->uf_def_args.ga_len)
{
// assume v:none used for default argument value
@@ -1606,7 +1625,7 @@ generate_PCALL(
expected = type->tt_args[
type->tt_argcount - 1]->tt_member;
else if (i >= type->tt_min_argcount
&& actual == &t_special)
&& actual->tt_type == VAR_SPECIAL)
expected = &t_any;
else
expected = type->tt_args[i];