diff options
Diffstat (limited to 'data/vim/patches/8.1.0134')
-rw-r--r-- | data/vim/patches/8.1.0134 | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0134 b/data/vim/patches/8.1.0134 new file mode 100644 index 000000000..ff07dfe27 --- /dev/null +++ b/data/vim/patches/8.1.0134 @@ -0,0 +1,724 @@ +To: vim_dev@googlegroups.com +Subject: Patch 8.1.0134 +Fcc: outbox +From: Bram Moolenaar <Bram@moolenaar.net> +Mime-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +------------ + +Patch 8.1.0134 +Problem: Lua interface does not support funcref. +Solution: Add funcref support. (Luis Carvalho) +Files: src/if_lua.c, src/testdir/test_lua.vim + + +*** ../vim-8.1.0133/src/if_lua.c 2017-12-16 18:17:27.000000000 +0100 +--- src/if_lua.c 2018-07-01 14:49:42.013143173 +0200 +*************** +*** 28,37 **** +--- 28,43 ---- + typedef win_T *luaV_Window; + typedef dict_T *luaV_Dict; + typedef list_T *luaV_List; ++ typedef struct { ++ typval_T tv; // funcref ++ typval_T args; ++ dict_T *self; // selfdict ++ } luaV_Funcref; + typedef void (*msgfunc_T)(char_u *); + + static const char LUAVIM_DICT[] = "dict"; + static const char LUAVIM_LIST[] = "list"; ++ static const char LUAVIM_FUNCREF[] = "funcref"; + static const char LUAVIM_BUFFER[] = "buffer"; + static const char LUAVIM_WINDOW[] = "window"; + static const char LUAVIM_FREE[] = "luaV_free"; +*************** +*** 55,63 **** + if (sandbox) luaL_error((L), "not allowed in sandbox") + #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) + #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) +! +! static luaV_List *luaV_pushlist (lua_State *L, list_T *lis); +! static luaV_Dict *luaV_pushdict (lua_State *L, dict_T *dic); + + #if LUA_VERSION_NUM <= 501 + #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) +--- 61,75 ---- + if (sandbox) luaL_error((L), "not allowed in sandbox") + #define luaV_msg(L) luaV_msgfunc((L), (msgfunc_T) msg) + #define luaV_emsg(L) luaV_msgfunc((L), (msgfunc_T) emsg) +! #define luaV_checktypval(L, a, v, msg) \ +! do { \ +! if (luaV_totypval(L, a, v) == FAIL) \ +! luaL_error(L, msg ": cannot convert value"); \ +! } while (0) +! +! static luaV_List *luaV_pushlist(lua_State *L, list_T *lis); +! static luaV_Dict *luaV_pushdict(lua_State *L, dict_T *dic); +! static luaV_Funcref *luaV_pushfuncref(lua_State *L, typval_T *tv); + + #if LUA_VERSION_NUM <= 501 + #define luaV_openlib(L, l, n) luaL_openlib(L, NULL, l, n) +*************** +*** 506,521 **** + else + lua_pushnil(L); + break; + default: + lua_pushnil(L); + } + } + +! /* converts lua value at 'pos' to typval 'tv' */ +! static void +! luaV_totypval (lua_State *L, int pos, typval_T *tv) + { +! switch(lua_type(L, pos)) { + case LUA_TBOOLEAN: + tv->v_type = VAR_SPECIAL; + tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); +--- 518,542 ---- + else + lua_pushnil(L); + break; ++ case VAR_FUNC: ++ luaV_pushfuncref(L, tv); ++ break; + default: + lua_pushnil(L); + } + } + +! /* +! * Converts lua value at 'pos' to typval 'tv'. +! * Returns OK or FAIL. +! */ +! static int +! luaV_totypval(lua_State *L, int pos, typval_T *tv) + { +! int status = OK; +! +! switch (lua_type(L, pos)) +! { + case LUA_TBOOLEAN: + tv->v_type = VAR_SPECIAL; + tv->vval.v_number = (varnumber_T) lua_toboolean(L, pos); +*************** +*** 533,540 **** + tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); + #endif + break; +! case LUA_TUSERDATA: { + void *p = lua_touserdata(L, pos); + if (lua_getmetatable(L, pos)) /* has metatable? */ + { + /* check list */ +--- 554,563 ---- + tv->vval.v_number = (varnumber_T) lua_tointeger(L, pos); + #endif + break; +! case LUA_TUSERDATA: +! { + void *p = lua_touserdata(L, pos); ++ + if (lua_getmetatable(L, pos)) /* has metatable? */ + { + /* check list */ +*************** +*** 545,551 **** + tv->vval.v_list = *((luaV_List *) p); + ++tv->vval.v_list->lv_refcount; + lua_pop(L, 2); /* MTs */ +! return; + } + /* check dict */ + luaV_getfield(L, LUAVIM_DICT); +--- 568,574 ---- + tv->vval.v_list = *((luaV_List *) p); + ++tv->vval.v_list->lv_refcount; + lua_pop(L, 2); /* MTs */ +! break; + } + /* check dict */ + luaV_getfield(L, LUAVIM_DICT); +*************** +*** 555,570 **** + tv->vval.v_dict = *((luaV_Dict *) p); + ++tv->vval.v_dict->dv_refcount; + lua_pop(L, 3); /* MTs */ +! return; + } +! lua_pop(L, 3); /* MTs */ + } +- break; + } + default: + tv->v_type = VAR_NUMBER; + tv->vval.v_number = 0; + } + } + + /* similar to luaL_addlstring, but replaces \0 with \n if toline and +--- 578,604 ---- + tv->vval.v_dict = *((luaV_Dict *) p); + ++tv->vval.v_dict->dv_refcount; + lua_pop(L, 3); /* MTs */ +! break; + } +! /* check funcref */ +! luaV_getfield(L, LUAVIM_FUNCREF); +! if (lua_rawequal(L, -1, -4)) +! { +! luaV_Funcref *f = (luaV_Funcref *) p; +! copy_tv(&f->tv, tv); +! lua_pop(L, 4); /* MTs */ +! break; +! } +! lua_pop(L, 4); /* MTs */ + } + } ++ /* FALLTHROUGH */ + default: + tv->v_type = VAR_NUMBER; + tv->vval.v_number = 0; ++ status = FAIL; + } ++ return status; + } + + /* similar to luaL_addlstring, but replaces \0 with \n if toline and +*************** +*** 646,652 **** + + #define luaV_pushtype(typ,tname,luatyp) \ + static luatyp * \ +! luaV_push##tname (lua_State *L, typ *obj) \ + { \ + luatyp *o = NULL; \ + if (obj == NULL) \ +--- 680,686 ---- + + #define luaV_pushtype(typ,tname,luatyp) \ + static luatyp * \ +! luaV_push##tname(lua_State *L, typ *obj) \ + { \ + luatyp *o = NULL; \ + if (obj == NULL) \ +*************** +*** 766,772 **** + else + { + typval_T v; +! luaV_totypval(L, 3, &v); + clear_tv(&li->li_tv); + copy_tv(&v, &li->li_tv); + clear_tv(&v); +--- 800,806 ---- + else + { + typval_T v; +! luaV_checktypval(L, 3, &v, "setting list item"); + clear_tv(&li->li_tv); + copy_tv(&v, &li->li_tv); + clear_tv(&v); +*************** +*** 783,793 **** + if (l->lv_lock) + luaL_error(L, "list is locked"); + lua_settop(L, 2); +! luaV_totypval(L, 2, &v); + if (list_append_tv(l, &v) == FAIL) + { + clear_tv(&v); +! luaL_error(L, "Failed to add item to list"); + } + clear_tv(&v); + lua_settop(L, 1); +--- 817,827 ---- + if (l->lv_lock) + luaL_error(L, "list is locked"); + lua_settop(L, 2); +! luaV_checktypval(L, 2, &v, "adding list item"); + if (list_append_tv(l, &v) == FAIL) + { + clear_tv(&v); +! luaL_error(L, "failed to add item to list"); + } + clear_tv(&v); + lua_settop(L, 1); +*************** +*** 811,821 **** + luaL_error(L, "invalid position"); + } + lua_settop(L, 2); +! luaV_totypval(L, 2, &v); + if (list_insert_tv(l, &v, li) == FAIL) + { + clear_tv(&v); +! luaL_error(L, "Failed to add item to list"); + } + clear_tv(&v); + lua_settop(L, 1); +--- 845,855 ---- + luaL_error(L, "invalid position"); + } + lua_settop(L, 2); +! luaV_checktypval(L, 2, &v, "inserting list item"); + if (list_insert_tv(l, &v, li) == FAIL) + { + clear_tv(&v); +! luaL_error(L, "failed to add item to list"); + } + clear_tv(&v); + lua_settop(L, 1); +*************** +*** 894,919 **** + } + + static int +! luaV_dict_index (lua_State *L) + { + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + char_u *key = (char_u *) luaL_checkstring(L, 2); + dictitem_T *di = dict_find(d, key, -1); + if (di == NULL) + lua_pushnil(L); + else + luaV_pushtypval(L, &di->di_tv); + return 1; + } + + static int +! luaV_dict_newindex (lua_State *L) + { + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + char_u *key = (char_u *) luaL_checkstring(L, 2); + dictitem_T *di; + if (d->dv_lock) + luaL_error(L, "dict is locked"); + di = dict_find(d, key, -1); + if (di == NULL) /* non-existing key? */ + { +--- 928,970 ---- + } + + static int +! luaV_dict_index(lua_State *L) + { + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + char_u *key = (char_u *) luaL_checkstring(L, 2); + dictitem_T *di = dict_find(d, key, -1); ++ + if (di == NULL) + lua_pushnil(L); + else ++ { + luaV_pushtypval(L, &di->di_tv); ++ if (di->di_tv.v_type == VAR_FUNC) /* funcref? */ ++ { ++ luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, -1); ++ f->self = d; /* keep "self" reference */ ++ d->dv_refcount++; ++ } ++ } + return 1; + } + + static int +! luaV_dict_newindex(lua_State *L) + { + dict_T *d = luaV_unbox(L, luaV_Dict, 1); + char_u *key = (char_u *) luaL_checkstring(L, 2); + dictitem_T *di; ++ typval_T v; + if (d->dv_lock) + luaL_error(L, "dict is locked"); ++ if (key != NULL && *key == NUL) ++ luaL_error(L, "empty key"); ++ if (!lua_isnil(L, 3)) { /* read value? */ ++ luaV_checktypval(L, 3, &v, "setting dict item"); ++ if (d->dv_scope == VAR_DEF_SCOPE && v.v_type == VAR_FUNC) ++ luaL_error(L, "cannot assign funcref to builtin scope"); ++ } + di = dict_find(d, key, -1); + if (di == NULL) /* non-existing key? */ + { +*************** +*** 934,942 **** + hash_remove(&d->dv_hashtab, hi); + dictitem_free(di); + } +! else { +! typval_T v; +! luaV_totypval(L, 3, &v); + copy_tv(&v, &di->di_tv); + clear_tv(&v); + } +--- 985,992 ---- + hash_remove(&d->dv_hashtab, hi); + dictitem_free(di); + } +! else +! { + copy_tv(&v, &di->di_tv); + clear_tv(&v); + } +*************** +*** 953,958 **** +--- 1003,1094 ---- + }; + + ++ /* ======= Funcref type ======= */ ++ ++ static luaV_Funcref * ++ luaV_newfuncref(lua_State *L, char_u *name) ++ { ++ luaV_Funcref *f = (luaV_Funcref *)lua_newuserdata(L, sizeof(luaV_Funcref)); ++ ++ if (name != NULL) ++ { ++ func_ref(name); /* as in copy_tv */ ++ f->tv.vval.v_string = vim_strsave(name); ++ } ++ f->tv.v_type = VAR_FUNC; ++ f->args.v_type = VAR_LIST; ++ f->self = NULL; ++ luaV_getfield(L, LUAVIM_FUNCREF); ++ lua_setmetatable(L, -2); ++ return f; ++ } ++ ++ static luaV_Funcref * ++ luaV_pushfuncref(lua_State *L, typval_T *tv) ++ { ++ luaV_Funcref *f = luaV_newfuncref(L, NULL); ++ copy_tv(tv, &f->tv); ++ clear_tv(tv); ++ return f; ++ } ++ ++ ++ luaV_type_tostring(funcref, LUAVIM_FUNCREF) ++ ++ static int ++ luaV_funcref_gc(lua_State *L) ++ { ++ luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); ++ ++ func_unref(f->tv.vval.v_string); ++ vim_free(f->tv.vval.v_string); ++ dict_unref(f->self); ++ return 0; ++ } ++ ++ /* equivalent to string(funcref) */ ++ static int ++ luaV_funcref_len(lua_State *L) ++ { ++ luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); ++ ++ lua_pushstring(L, (const char *) f->tv.vval.v_string); ++ return 1; ++ } ++ ++ static int ++ luaV_funcref_call(lua_State *L) ++ { ++ luaV_Funcref *f = (luaV_Funcref *) lua_touserdata(L, 1); ++ int i, n = lua_gettop(L) - 1; /* #args */ ++ int status; ++ typval_T v, rettv; ++ ++ f->args.vval.v_list = list_alloc(); ++ rettv.v_type = VAR_UNKNOWN; /* as in clear_tv */ ++ for (i = 0; i < n; i++) { ++ luaV_checktypval(L, i + 2, &v, "calling funcref"); ++ list_append_tv(f->args.vval.v_list, &v); ++ } ++ status = func_call(f->tv.vval.v_string, &f->args, NULL, f->self, &rettv); ++ if (status == OK) ++ luaV_pushtypval(L, &rettv); ++ clear_tv(&f->args); ++ clear_tv(&rettv); ++ if (status != OK) ++ luaL_error(L, "cannot call funcref"); ++ return 1; ++ } ++ ++ static const luaL_Reg luaV_Funcref_mt[] = { ++ {"__tostring", luaV_funcref_tostring}, ++ {"__gc", luaV_funcref_gc}, ++ {"__len", luaV_funcref_len}, ++ {"__call", luaV_funcref_call}, ++ {NULL, NULL} ++ }; ++ ++ + /* ======= Buffer type ======= */ + + luaV_newtype(buf_T, buffer, luaV_Buffer, LUAVIM_BUFFER) +*************** +*** 1033,1039 **** + curbuf = buf; + luaL_error(L, "cannot delete line"); + } +! else { + deleted_lines_mark(n, 1L); + if (b == curwin->w_buffer) /* fix cursor in current window? */ + { +--- 1169,1176 ---- + curbuf = buf; + luaL_error(L, "cannot delete line"); + } +! else +! { + deleted_lines_mark(n, 1L); + if (b == curwin->w_buffer) /* fix cursor in current window? */ + { +*************** +*** 1371,1392 **** + static int + luaV_list(lua_State *L) + { +! list_T *l = list_alloc(); + if (l == NULL) + lua_pushnil(L); + else + luaV_newlist(L, l); + return 1; + } + + static int + luaV_dict(lua_State *L) + { +! dict_T *d = dict_alloc(); + if (d == NULL) + lua_pushnil(L); + else + luaV_newdict(L, d); + return 1; + } + +--- 1508,1591 ---- + static int + luaV_list(lua_State *L) + { +! list_T *l; +! int initarg = !lua_isnoneornil(L, 1); +! +! if (initarg && lua_type(L, 1) != LUA_TTABLE) +! luaL_error(L, "table expected, got %s", luaL_typename(L, 1)); +! l = list_alloc(); + if (l == NULL) + lua_pushnil(L); + else ++ { + luaV_newlist(L, l); ++ if (initarg) { /* traverse table to init dict */ ++ int notnil, i = 0; ++ typval_T v; ++ do { ++ lua_rawgeti(L, 1, ++i); ++ notnil = !lua_isnil(L, -1); ++ if (notnil) { ++ luaV_checktypval(L, -1, &v, "vim.list"); ++ list_append_tv(l, &v); ++ } ++ lua_pop(L, 1); /* value */ ++ } while (notnil); ++ } ++ } + return 1; + } + + static int + luaV_dict(lua_State *L) + { +! dict_T *d; +! int initarg = !lua_isnoneornil(L, 1); +! +! if (initarg && lua_type(L, 1) != LUA_TTABLE) +! luaL_error(L, "table expected, got %s", luaL_typename(L, 1)); +! d = dict_alloc(); + if (d == NULL) + lua_pushnil(L); + else ++ { + luaV_newdict(L, d); ++ if (initarg) /* traverse table to init dict */ ++ { ++ lua_pushnil(L); ++ while (lua_next(L, 1)) ++ { ++ char_u *key; ++ dictitem_T *di; ++ typval_T v; ++ lua_pushvalue(L, -2); /* dup key in case it's a number */ ++ key = (char_u *) lua_tostring(L, -1); ++ if (key != NULL && *key == NUL) ++ luaL_error(L, "table has empty key"); ++ luaV_checktypval(L, -2, &v, "vim.dict"); /* value */ ++ di = dictitem_alloc(key); ++ if (di == NULL || dict_add(d, di) == FAIL) { ++ vim_free(di); ++ lua_pushnil(L); ++ return 1; ++ } ++ copy_tv(&v, &di->di_tv); ++ clear_tv(&v); ++ lua_pop(L, 2); /* key copy and value */ ++ } ++ } ++ } ++ return 1; ++ } ++ ++ static int ++ luaV_funcref(lua_State *L) ++ { ++ const char *name = luaL_checkstring(L, 1); ++ /* note: not checking if function exists (needs function_exists) */ ++ if (name == NULL || *name == NUL || VIM_ISDIGIT(*name)) ++ luaL_error(L, "invalid function name: %s", name); ++ luaV_newfuncref(L, (char_u *) name); + return 1; + } + +*************** +*** 1402,1408 **** + FOR_ALL_BUFFERS(buf) + if (buf->b_fnum == n) break; + } +! else { /* by name */ + size_t l; + const char *s = lua_tolstring(L, 1, &l); + FOR_ALL_BUFFERS(buf) +--- 1601,1608 ---- + FOR_ALL_BUFFERS(buf) + if (buf->b_fnum == n) break; + } +! else // by name +! { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + FOR_ALL_BUFFERS(buf) +*************** +*** 1472,1477 **** +--- 1672,1683 ---- + lua_pushstring(L, "dict"); + return 1; + } ++ luaV_getfield(L, LUAVIM_FUNCREF); ++ if (lua_rawequal(L, -1, 2)) ++ { ++ lua_pushstring(L, "funcref"); ++ return 1; ++ } + luaV_getfield(L, LUAVIM_BUFFER); + if (lua_rawequal(L, -1, 2)) + { +*************** +*** 1497,1502 **** +--- 1703,1709 ---- + {"line", luaV_line}, + {"list", luaV_list}, + {"dict", luaV_dict}, ++ {"funcref", luaV_funcref}, + {"buffer", luaV_buffer}, + {"window", luaV_window}, + {"open", luaV_open}, +*************** +*** 1537,1543 **** + luaV_emsg(L); + return 0; + } +! luaV_totypval(L, -1, rettv); + return 0; + } + +--- 1744,1751 ---- + luaV_emsg(L); + return 0; + } +! if (luaV_totypval(L, -1, rettv) == FAIL) +! EMSG("luaeval: cannot convert value"); + return 0; + } + +*************** +*** 1612,1617 **** +--- 1820,1828 ---- + luaV_newmetatable(L, LUAVIM_DICT); + lua_pushvalue(L, 1); + luaV_openlib(L, luaV_Dict_mt, 1); ++ luaV_newmetatable(L, LUAVIM_FUNCREF); ++ lua_pushvalue(L, 1); ++ luaV_openlib(L, luaV_Funcref_mt, 1); + luaV_newmetatable(L, LUAVIM_BUFFER); + lua_pushvalue(L, 1); /* cache table */ + luaV_openlib(L, luaV_Buffer_mt, 1); +*** ../vim-8.1.0133/src/testdir/test_lua.vim 2018-06-30 21:50:16.856674912 +0200 +--- src/testdir/test_lua.vim 2018-07-01 15:00:55.884371772 +0200 +*************** +*** 397,402 **** +--- 397,425 ---- + lua str, k, v, d = nil, nil, nil, nil + endfunc + ++ func Test_funcref() ++ function I(x) ++ return a:x ++ endfunction ++ let R = function('I') ++ lua i1 = vim.funcref"I" ++ lua i2 = vim.eval"R" ++ lua msg = "funcref|test|" .. (#i2(i1) == #i1(i2) and "OK" or "FAIL") ++ lua msg = vim.funcref"tr"(msg, "|", " ") ++ call assert_equal("funcref test OK", luaeval('msg')) ++ ++ " dict funcref ++ function Mylen() dict ++ return len(self.data) ++ endfunction ++ let l = [0, 1, 2, 3] ++ let mydict = {'data': l} ++ lua d = vim.eval"mydict" ++ lua d.len = vim.funcref"Mylen" -- assign d as 'self' ++ lua res = (d.len() == vim.funcref"len"(vim.eval"l")) and "OK" or "FAIL" ++ call assert_equal("OK", luaeval('res')) ++ endfunc ++ + " Test vim.type() + func Test_type() + " The following values are identical to Lua's type function. +*************** +*** 414,419 **** +--- 437,443 ---- + call assert_equal('buffer', luaeval('vim.type(vim.buffer())')) + call assert_equal('list', luaeval('vim.type(vim.list())')) + call assert_equal('dict', luaeval('vim.type(vim.dict())')) ++ call assert_equal('funcref', luaeval('vim.type(vim.funcref("Test_type"))')) + endfunc + + " Test vim.open() +*** ../vim-8.1.0133/src/version.c 2018-06-30 22:40:39.097551835 +0200 +--- src/version.c 2018-07-01 15:01:56.939951330 +0200 +*************** +*** 791,792 **** +--- 791,794 ---- + { /* Add new patch number below this line */ ++ /**/ ++ 134, + /**/ + +-- +hundred-and-one symptoms of being an internet addict: +162. You go outside and look for a brightness knob to turn down the sun. + + /// 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 /// |