2016-07-22 14:12 GMT+03:00 Nikolay Aleksandrovich Pavlov <zyx....@gmail.com>: > 2016-07-22 14:09 GMT+03:00 Nikolay Aleksandrovich Pavlov <zyx....@gmail.com>: >> 2016-07-20 21:23 GMT+03:00 Ken Takata <ktakata65...@gmail.com>: >>> Hi, >>> >>> 2016/7/19 Tue 23:18:30 UTC+9 ZyX wrote: >>>> 2016-07-19 17:15 GMT+03:00 Nikolay Aleksandrovich Pavlov >>>> <zyx....@gmail.com>: >>>> > 2016-07-19 16:46 GMT+03:00 Ken Takata <ktakata65...@gmail.com>: >>>> >> Hi, >>>> >> >>>> >> 2016/7/18 Mon 11:26:23 UTC+9 Ken Takata wrote: >>>> >>> Hi, >>>> >>> >>>> >>> 2016/7/17 Sun 21:26:29 UTC+9 itchyny wrote: >>>> >>> > I additionally submit another test case. >>>> >>> > >>>> >>> > let Y = {f -> (({x -> f ({y -> x(x)(y)})}) ({x -> f ({y -> >>>> >>> > x(x)(y)})}))} >>>> >>> > let Fact = {f -> {x -> (x == 0 ? 1 : x * f(x - 1))}} >>>> >>> > echo Y(Fact)(5) >>>> >>> > >>>> >>> > I expect this script prints 120 but I got E110: Missing ')' in >>>> >>> > 7.4.2049 (and also with the experimental patch). >>>> >>> > Is there something wrong with the above code or is there some bug in >>>> >>> > the parsing code in eval.c? >>>> >>> > >>>> >>> > Here are the counterparts in Python >>>> >>> > Y = lambda f: (lambda x: f (lambda y: x(x)(y))) (lambda x: f (lambda >>>> >>> > y: x(x)(y))) >>>> >>> > Fact = lambda f: lambda x: (1 if x == 0 else x * f(x - 1)) >>>> >>> > print Y(Fact)(5) >>>> >>> > >>>> >>> > and in JavaScript >>>> >>> > var Y = function(f){ return (function(x){ return f (function(y){ >>>> >>> > return x(x)(y); }); }) (function(x){ return f (function(y){ return >>>> >>> > x(x)(y); }); }); }; >>>> >>> > var Fact = function(f){ return function(x){ return (x == 0 ? 1 : x * >>>> >>> > f(x - 1)); }; }; >>>> >>> > console.log(Y(Fact)(5)); >>>> >>> > >>>> >>> > reference: >>>> >>> > https://en.wikipedia.org/wiki/Lambda_calculus#Recursion_and_fixed_points, >>>> >>> > >>>> >>> > https://en.wikipedia.org/wiki/Fixed-point_combinator#Fixed_point_combinators_in_lambda_calculus >>>> >>> >>>> >>> I have updated the patch for the latest code: >>>> >>> https://bitbucket.org/k_takata/vim-ktakata-mq/src/006cdbbeef26201154d04b7dfe1aed119321acb1/lambda-update.patch?at=default >>>> >>> >>>> >>> The SEGV on test_alot.vim seems fixed. >>>> >>> >>>> >>> >>>> >>> > let Y = {f -> (({x -> f ({y -> x(x)(y)})}) ({x -> f ({y -> >>>> >>> > x(x)(y)})}))} >>>> >>> >>>> >>> This still causes errors. Not sure why. Simpler example would be >>>> >>> better. >>>> >> >>>> >> I have updated the patch: >>>> >> https://bitbucket.org/k_takata/vim-ktakata-mq/src/29d0a0ecfa23f70852fa3f5c33e15ea629cd17b4/lambda-update.patch?fileviewer=file-view-default >>>> > >>>> > What happens in case of >>>> > >>>> > function Foo(arg) >>>> > let d = {} >>>> > let d.f = {-> d} >>>> > return d.f >>>> > endfunction >>>> > let i = 0 >>>> > while i < 1000000 | call Foo() | endwhile >>>> > >>>> > ? Specifically I suspect memory leak here because lambdas now are >>>> > (implicit) containers, but you did not touch GC. >>>> >>>> Forgot `let i += 1`. Though it should still be interruptible by >>>> `<C-c>`, so `while 1` may even be better for a quick test: if >>>> everything is fine, memory usage will drop after `<C-c>`, but may >>>> increase before (AFAIR, by default full GC which checks for cycles is >>>> run at main loop when waiting for characters). If not, it will not. >>> >>> I have slightly updated the patch: >>> https://bitbucket.org/k_takata/vim-ktakata-mq/src/162e04a587ce7e0b6b4ce46afe092cc4a5ab21e0/lambda-update.patch?fileviewer=file-view-default >>> >>> Some tests based on mattn's patch are added. (Not all yet.) >>> >>> >>> function! Foo() >>> let d = {} >>> let d.f = {-> d} >>> "let d.f = d >>> return d.f >>> endfunction >>> let i = 0 | while i < 1000000 | call Foo() | let i+= 1 | endwhile >>> >>> While running this loop, memory usage increases, but it decreases after >>> ending >>> the loop. This is almost the same when the line "let d.f = d" is used >>> instead >>> of the lambda expression. However more tests might be needed to check that >>> there is no memory leakage. >> >> I was wrong regarding the consequences and why you should alter the >> GC: it is not memory leak because cycle is not GC’d. It is *crash* >> because Vim does not know that dictionary is referenced: >> >> ```VimL >> function F() >> let d = {} >> return {-> d} >> endfunction >> let L = F() >> call garbagecollect(1) >> call feedkeys(":echo L()\n", 'n') >> ``` >> >> Save to `test.vim` and run as `vim -u NONE -i NONE -N -S test.vim`. >> When I use it in Vim with optimizations it crashes immediately: >> >> ``` >> #0 0x00007f85da75b947 in kill () from /lib64/libc.so.6 >> #1 0x0000000000598928 in mch_exit () >> #2 0x00000000006c8f87 in getout () >> #3 0x000000000059695e in deathtrap () >> #4 <signal handler called> >> #5 0x00007f85da7aa5ba in strlen () from /lib64/libc.so.6 >> #6 0x0000000000474173 in string_quote () >> #7 0x00000000004582ac in dict2string () >> #8 0x0000000000476aa5 in echo_string_core () >> #9 0x000000000047d253 in ex_echo () >> #10 0x00000000004c13cb in do_one_cmd () >> #11 0x00000000004c51fa in do_cmdline () >> #12 0x000000000055f545 in nv_colon () >> #13 0x000000000056cb48 in normal_cmd () >> #14 0x00000000006c8b65 in main_loop () >> #15 0x000000000043c21c in main () >> ``` >> >> When not it crashes and hangs either immediately or when I press :, if >> I comment garbagecollect() call, but then type it myself and exit, I >> get >> >> ``` >> #0 0x0000000000950a60 in ?? () >> #1 0x0000000000594f3f in vim_regexec_both (rmp=0x942860, >> line=0x94ebd0 <incomplete sequence \354\224>, col=0, nl=0) at >> regexp.c:8122 >> #2 0x0000000000594ed9 in vim_regexec_prog (prog=0x93eb20 >> <clip_exclude_prog>, ignore_case=0, line=0x94ebd0 <incomplete sequence >> \354\224>, col=0) at regexp.c:8166 >> #3 0x00000000005837b8 in x_connect_to_server () at os_unix.c:1674 >> #4 0x000000000057d3e9 in get_x11_windis () at os_unix.c:1767 >> #5 0x000000000057d26f in mch_settitle (title=0x983c20 "\340P\230", >> icon=0x0) at os_unix.c:2150 >> #6 0x000000000057d971 in mch_restore_title (which=3) at os_unix.c:2228 >> #7 0x000000000057eb2c in mch_exit (r=1) at os_unix.c:3279 >> #8 0x00000000006a8544 in getout (exitval=1) at main.c:1493 >> #9 0x000000000052c7cb in preserve_exit () at misc1.c:9494 >> #10 0x00000000005847bd in deathtrap (sigarg=11) at os_unix.c:1164 >> #11 <signal handler called> >> #12 0x00007fa18d008d5a in malloc_consolidate () from /lib64/libc.so.6 >> #13 0x00007fa18d009a70 in _int_free () from /lib64/libc.so.6 >> #14 0x00000000005312ee in vim_free (x=0x968660) at misc2.c:1698 >> #15 0x00000000005d4c73 in free_screenlines () at screen.c:8833 >> #16 0x000000000053126f in free_all_mem () at misc2.c:1231 >> #17 0x000000000057eba6 in mch_exit (r=0) at os_unix.c:3330 >> #18 0x00000000006a8544 in getout (exitval=0) at main.c:1493 >> #19 0x00000000004b76c1 in ex_quit_all (eap=0x7ffda0419aa8) at ex_docmd.c:7249 >> #20 0x00000000004a8b47 in do_one_cmd (cmdlinep=0x7ffda041a208, >> sourcing=0, cstack=0x7ffda0419d50, fgetline=0x4c83e0 <getexline>, >> cookie=0x0) at ex_docmd.c:2925 >> #21 0x00000000004a4a70 in do_cmdline (cmdline=0x0, fgetline=0x4c83e0 >> <getexline>, cookie=0x0, flags=0) at ex_docmd.c:1110 >> #22 0x000000000054e548 in nv_colon (cap=0x7ffda041a348) at normal.c:5323 >> #23 0x0000000000545222 in normal_cmd (oap=0x7ffda041a3e8, toplevel=1) >> at normal.c:1149 >> #24 0x00000000006a8ed4 in main_loop (cmdwin=0, noexmode=0) at main.c:1308 >> #25 0x00000000006a5509 in main (argc=8, argv=0x7ffda041a738) at main.c:874 >> ``` >> >> When hanging bt is >> >> ``` >> #0 0x00007f5203cd092b in __lll_lock_wait_private () from /lib64/libc.so.6 >> #1 0x00007f5203c54766 in malloc () from /lib64/libc.so.6 >> #2 0x0000000000530b5e in lalloc (size=14560, message=1) at misc2.c:920 >> #3 0x00000000005bd796 in nfa_regmatch (prog=0x950a70, start=0x950c50, >> submatch=0x942568, m=0x942378) at ./regexp_nfa.c:5547 >> #4 0x00000000005bd1d6 in nfa_regtry (prog=0x950a70, col=0, tm=0x0) at >> ./regexp_nfa.c:6967 >> #5 0x00000000005bcce0 in nfa_regexec_both (line=0x94ebd0 >> "konsole-256color", startcol=0, tm=0x0) at ./regexp_nfa.c:7159 >> #6 0x00000000005a4fab in nfa_regexec_nl (rmp=0x942860, line=0x94ebd0 >> "konsole-256color", col=0, line_lbr=0) at ./regexp_nfa.c:7318 >> #7 0x0000000000594f3f in vim_regexec_both (rmp=0x942860, >> line=0x94ebd0 "konsole-256color", col=0, nl=0) at regexp.c:8122 >> #8 0x0000000000594ed9 in vim_regexec_prog (prog=0x93eb20 >> <clip_exclude_prog>, ignore_case=0, line=0x94ebd0 "konsole-256color", >> col=0) at regexp.c:8166 >> #9 0x00000000005837b8 in x_connect_to_server () at os_unix.c:1674 >> #10 0x000000000057d3e9 in get_x11_windis () at os_unix.c:1767 >> #11 0x000000000057d26f in mch_settitle (title=0x983c20 "[Нет имени] - >> VIM", icon=0x0) at os_unix.c:2150 >> #12 0x000000000057d971 in mch_restore_title (which=3) at os_unix.c:2228 >> #13 0x000000000057eb2c in mch_exit (r=1) at os_unix.c:3279 >> #14 0x00000000006a8544 in getout (exitval=1) at main.c:1493 >> #15 0x000000000052c7cb in preserve_exit () at misc1.c:9494 >> #16 0x00000000005847bd in deathtrap (sigarg=11) at os_unix.c:1164 >> #17 <signal handler called> >> #18 0x00007f5203c53184 in _int_malloc () from /lib64/libc.so.6 >> #19 0x00007f5203c54778 in malloc () from /lib64/libc.so.6 >> #20 0x0000000000530b5e in lalloc (size=29, message=1) at misc2.c:920 >> #21 0x0000000000530af8 in alloc (size=29) at misc2.c:818 >> #22 0x0000000000642c53 in call_user_func (fp=0x9b02b0, argcount=0, >> argvars=0x7ffd62dee650, rettv=0x7ffd62deee60, firstline=1, lastline=1, >> selfdict=0x0) at userfunc.c:897 >> #23 0x0000000000641ac3 in call_func (funcname=0x9b03f0 "<lambda>1", >> len=9, rettv=0x7ffd62deee60, argcount_in=0, argvars_in=0x7ffd62dee650, >> firstline=1, lastline=1, doesrange=0x7ffd62dee8f4, evaluate=1, >> partial=0x0, selfdict_in=0x0) >> at userfunc.c:1347 >> #24 0x00000000006414da in get_func_tv (name=0x9b03f0 "<lambda>1", >> len=9, rettv=0x7ffd62deee60, arg=0x7ffd62deee70, firstline=1, >> lastline=1, doesrange=0x7ffd62dee8f4, evaluate=1, partial=0x0, >> selfdict=0x0) at userfunc.c:514 >> #25 0x0000000000471f66 in eval7 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1, want_string=0) at eval.c:4344 >> #26 0x00000000004715bf in eval6 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1, want_string=0) at eval.c:3978 >> #27 0x0000000000471185 in eval5 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1) at eval.c:3794 >> #28 0x00000000004704db in eval4 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1) at eval.c:3493 >> #29 0x00000000004702ea in eval3 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1) at eval.c:3410 >> #30 0x000000000046608a in eval2 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1) at eval.c:3342 >> #31 0x0000000000461b13 in eval1 (arg=0x7ffd62deee70, >> rettv=0x7ffd62deee60, evaluate=1) at eval.c:3270 >> #32 0x000000000046aec6 in ex_echo (eap=0x7ffd62def0e8) at eval.c:8166 >> #33 0x00000000004a8b47 in do_one_cmd (cmdlinep=0x7ffd62def848, >> sourcing=0, cstack=0x7ffd62def390, fgetline=0x4c83e0 <getexline>, >> cookie=0x0) at ex_docmd.c:2925 >> #34 0x00000000004a4a70 in do_cmdline (cmdline=0x0, fgetline=0x4c83e0 >> <getexline>, cookie=0x0, flags=0) at ex_docmd.c:1110 >> #35 0x000000000054e548 in nv_colon (cap=0x7ffd62def988) at normal.c:5323 >> #36 0x0000000000545222 in normal_cmd (oap=0x7ffd62defa28, toplevel=1) >> at normal.c:1149 >> #37 0x00000000006a8ed4 in main_loop (cmdwin=0, noexmode=0) at main.c:1308 >> #38 0x00000000006a5509 in main (argc=8, argv=0x7ffd62defd78) at main.c:874 >> ``` > > Last two backtraces are from 4c2524dd2403 plus your patch.
(7.4.2089, using mercurial mirror) > >> >>> >>> >>>> > Also you should not omit using dict_alloc(). `copy_vars()` looks like >>>> > something that should be in dict.c. Also it looks like something that >>>> > is already implemented: looks much like extend(), so you probably just >>>> > need to employ `dict_extend()`. Probably modifying it, but I doubt >>> >>> I didn't notice the function dict_extend(). >>> >>>> > that `copyitem = FALSE` is valid, wanting to see whether your example >>>> > works with `let Bar = Foo("test: using allocated string")`. >>> >>> l: and a: dictionaries are handled differently in the function >>> call_user_func(). >>> >>> >>>> > And, I guess, Bram will reject this because you copy the whole l: and >>>> > a: dictionaries. >>> >>> Not all l: and d: dictionaries are copied. Only used variables are copied, >>> but they are copied twice. >>> >>> 1. When parsing a lambda, check all used l: and a: variables and copy them >>> to >>> dictionaries in ufunc_T structure. >>> 2. When executing the lambda, the all l: and a: variables in ufunc_T are >>> copied to l: and a: dictionaries in funccall_T structure. >>> >>> Mattn's implementation was storing only the references to l: and a: (but >>> even >>> they are not used). Not sure which is better. >>> >>> Regards, >>> Ken Takata >>> >>> -- >>> -- >>> You received this message from the "vim_dev" maillist. >>> Do not top-post! Type your reply below the text you are replying to. >>> For more information, visit http://www.vim.org/maillist.php >>> >>> --- >>> You received this message because you are subscribed to the Google Groups >>> "vim_dev" group. >>> To unsubscribe from this group and stop receiving emails from it, send an >>> email to vim_dev+unsubscr...@googlegroups.com. >>> For more options, visit https://groups.google.com/d/optout. -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.