changeset 3618:c052f3b79b99 v7.3.569

updated for version 7.3.569 Problem: Evaluating Vim expression in Python is insufficient. Solution: Add vim.bindeval(). Also add pyeval() and py3eval(). (ZyX)
author Bram Moolenaar <bram@vim.org>
date Fri, 29 Jun 2012 12:54:53 +0200
parents 74d62fbf05c9
children 08ea0523a078
files src/eval.c src/if_lua.c src/if_py_both.h src/if_python.c src/if_python3.c src/proto/eval.pro src/proto/if_python.pro src/proto/if_python3.pro src/testdir/Make_amiga.mak src/testdir/Make_dos.mak src/testdir/Make_ming.mak src/testdir/Make_os2.mak src/testdir/Makefile src/testdir/test86.in src/testdir/test86.ok src/testdir/test87.in src/testdir/test87.ok src/version.c
diffstat 18 files changed, 2413 insertions(+), 244 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -424,30 +424,21 @@ static int get_string_tv __ARGS((char_u 
 static int get_lit_string_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
 static int get_list_tv __ARGS((char_u **arg, typval_T *rettv, int evaluate));
 static int rettv_list_alloc __ARGS((typval_T *rettv));
-static listitem_T *listitem_alloc __ARGS((void));
 static void listitem_free __ARGS((listitem_T *item));
-static void listitem_remove __ARGS((list_T *l, listitem_T *item));
 static long list_len __ARGS((list_T *l));
 static int list_equal __ARGS((list_T *l1, list_T *l2, int ic, int recursive));
 static int dict_equal __ARGS((dict_T *d1, dict_T *d2, int ic, int recursive));
 static int tv_equal __ARGS((typval_T *tv1, typval_T *tv2, int ic, int recursive));
-static listitem_T *list_find __ARGS((list_T *l, long n));
 static long list_find_nr __ARGS((list_T *l, long idx, int *errorp));
 static long list_idx_of_item __ARGS((list_T *l, listitem_T *item));
-static void list_append __ARGS((list_T *l, listitem_T *item));
 static int list_append_number __ARGS((list_T *l, varnumber_T n));
-static int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
 static int list_extend __ARGS((list_T	*l1, list_T *l2, listitem_T *bef));
 static int list_concat __ARGS((list_T *l1, list_T *l2, typval_T *tv));
 static list_T *list_copy __ARGS((list_T *orig, int deep, int copyID));
-static void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
 static char_u *list2string __ARGS((typval_T *tv, int copyID));
 static int list_join_inner __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo_style, int copyID, garray_T *join_gap));
 static int list_join __ARGS((garray_T *gap, list_T *l, char_u *sep, int echo, int copyID));
 static int free_unref_items __ARGS((int copyID));
-static void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
-static void set_ref_in_list __ARGS((list_T *l, int copyID));
-static void set_ref_in_item __ARGS((typval_T *tv, int copyID));
 static int rettv_dict_alloc __ARGS((typval_T *rettv));
 static void dict_free __ARGS((dict_T *d, int recurse));
 static dictitem_T *dictitem_copy __ARGS((dictitem_T *org));
@@ -654,6 +645,12 @@ static void f_pow __ARGS((typval_T *argv
 static void f_prevnonblank __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_printf __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_pumvisible __ARGS((typval_T *argvars, typval_T *rettv));
+#ifdef FEAT_PYTHON3
+static void f_py3eval __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
+#ifdef FEAT_PYTHON
+static void f_pyeval __ARGS((typval_T *argvars, typval_T *rettv));
+#endif
 static void f_range __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_readfile __ARGS((typval_T *argvars, typval_T *rettv));
 static void f_reltime __ARGS((typval_T *argvars, typval_T *rettv));
@@ -824,8 +821,6 @@ static int script_autoload __ARGS((char_
 static char_u *autoload_name __ARGS((char_u *name));
 static void cat_func_name __ARGS((char_u *buf, ufunc_T *fp));
 static void func_free __ARGS((ufunc_T *fp));
-static void func_unref __ARGS((char_u *name));
-static void func_ref __ARGS((char_u *name));
 static void call_user_func __ARGS((ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict));
 static int can_free_funccal __ARGS((funccall_T *fc, int copyID)) ;
 static void free_funccal __ARGS((funccall_T *fc, int free_val));
@@ -5927,7 +5922,7 @@ list_free(l, recurse)
 /*
  * Allocate a list item.
  */
-    static listitem_T *
+    listitem_T *
 listitem_alloc()
 {
     return (listitem_T *)alloc(sizeof(listitem_T));
@@ -5947,7 +5942,7 @@ listitem_free(item)
 /*
  * Remove a list item from a List and free it.  Also clears the value.
  */
-    static void
+    void
 listitem_remove(l, item)
     list_T  *l;
     listitem_T *item;
@@ -6123,7 +6118,7 @@ tv_equal(tv1, tv2, ic, recursive)
  * A negative index is counted from the end; -1 is the last item.
  * Returns NULL when "n" is out of range.
  */
-    static listitem_T *
+    listitem_T *
 list_find(l, n)
     list_T	*l;
     long	n;
@@ -6265,7 +6260,7 @@ list_idx_of_item(l, item)
 /*
  * Append item "item" to the end of list "l".
  */
-    static void
+    void
 list_append(l, item)
     list_T	*l;
     listitem_T	*item;
@@ -6378,7 +6373,7 @@ list_append_number(l, n)
  * If "item" is NULL append at the end.
  * Return FAIL when out of memory.
  */
-    static int
+    int
 list_insert_tv(l, tv, item)
     list_T	*l;
     typval_T	*tv;
@@ -6523,7 +6518,7 @@ list_copy(orig, deep, copyID)
  * Remove items "item" to "item2" from list "l".
  * Does not free the listitem or the value!
  */
-    static void
+    void
 list_remove(l, item, item2)
     list_T	*l;
     listitem_T	*item;
@@ -6785,6 +6780,14 @@ garbage_collect()
     set_ref_in_lua(copyID);
 #endif
 
+#ifdef FEAT_PYTHON
+    set_ref_in_python(copyID);
+#endif
+
+#ifdef FEAT_PYTHON3
+    set_ref_in_python3(copyID);
+#endif
+
     /*
      * 2. Free lists and dictionaries that are not referenced.
      */
@@ -6870,7 +6873,7 @@ free_unref_items(copyID)
 /*
  * Mark all lists and dicts referenced through hashtab "ht" with "copyID".
  */
-    static void
+    void
 set_ref_in_ht(ht, copyID)
     hashtab_T	*ht;
     int		copyID;
@@ -6890,7 +6893,7 @@ set_ref_in_ht(ht, copyID)
 /*
  * Mark all lists and dicts referenced through list "l" with "copyID".
  */
-    static void
+    void
 set_ref_in_list(l, copyID)
     list_T	*l;
     int		copyID;
@@ -6904,7 +6907,7 @@ set_ref_in_list(l, copyID)
 /*
  * Mark all lists and dicts referenced through typval "tv" with "copyID".
  */
-    static void
+    void
 set_ref_in_item(tv, copyID)
     typval_T	*tv;
     int		copyID;
@@ -7986,6 +7989,12 @@ static struct fst
     {"prevnonblank",	1, 1, f_prevnonblank},
     {"printf",		2, 19, f_printf},
     {"pumvisible",	0, 0, f_pumvisible},
+#ifdef FEAT_PYTHON3
+    {"py3eval",		1, 1, f_py3eval},
+#endif
+#ifdef FEAT_PYTHON
+    {"pyeval",		1, 1, f_pyeval},
+#endif
     {"range",		1, 3, f_range},
     {"readfile",	1, 3, f_readfile},
     {"reltime",		0, 2, f_reltime},
@@ -9150,6 +9159,45 @@ f_byteidx(argvars, rettv)
 #endif
 }
 
+    int
+func_call(name, args, selfdict, rettv)
+    char_u	*name;
+    typval_T	*args;
+    dict_T	*selfdict;
+    typval_T	*rettv;
+{
+    listitem_T	*item;
+    typval_T	argv[MAX_FUNC_ARGS + 1];
+    int		argc = 0;
+    int		dummy;
+    int		r = 0;
+
+    for (item = args->vval.v_list->lv_first; item != NULL;
+							 item = item->li_next)
+    {
+	if (argc == MAX_FUNC_ARGS)
+	{
+	    EMSG(_("E699: Too many arguments"));
+	    break;
+	}
+	/* Make a copy of each argument.  This is needed to be able to set
+	 * v_lock to VAR_FIXED in the copy without changing the original list.
+	 */
+	copy_tv(&item->li_tv, &argv[argc++]);
+    }
+
+    if (item == NULL)
+	r = call_func(name, (int)STRLEN(name), rettv, argc, argv,
+				 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
+						      &dummy, TRUE, selfdict);
+
+    /* Free the arguments. */
+    while (argc > 0)
+	clear_tv(&argv[--argc]);
+
+    return r;
+}
+
 /*
  * "call(func, arglist)" function
  */
@@ -9159,10 +9207,6 @@ f_call(argvars, rettv)
     typval_T	*rettv;
 {
     char_u	*func;
-    typval_T	argv[MAX_FUNC_ARGS + 1];
-    int		argc = 0;
-    listitem_T	*item;
-    int		dummy;
     dict_T	*selfdict = NULL;
 
     if (argvars[1].v_type != VAR_LIST)
@@ -9190,28 +9234,7 @@ f_call(argvars, rettv)
 	selfdict = argvars[2].vval.v_dict;
     }
 
-    for (item = argvars[1].vval.v_list->lv_first; item != NULL;
-							 item = item->li_next)
-    {
-	if (argc == MAX_FUNC_ARGS)
-	{
-	    EMSG(_("E699: Too many arguments"));
-	    break;
-	}
-	/* Make a copy of each argument.  This is needed to be able to set
-	 * v_lock to VAR_FIXED in the copy without changing the original list.
-	 */
-	copy_tv(&item->li_tv, &argv[argc++]);
-    }
-
-    if (item == NULL)
-	(void)call_func(func, (int)STRLEN(func), rettv, argc, argv,
-				 curwin->w_cursor.lnum, curwin->w_cursor.lnum,
-						      &dummy, TRUE, selfdict);
-
-    /* Free the arguments. */
-    while (argc > 0)
-	clear_tv(&argv[--argc]);
+    (void)func_call(func, &argvars[1], selfdict, rettv);
 }
 
 #ifdef FEAT_FLOAT
@@ -14424,6 +14447,40 @@ f_pumvisible(argvars, rettv)
 #endif
 }
 
+#ifdef FEAT_PYTHON3
+/*
+ * "py3eval()" function
+ */
+    static void
+f_py3eval(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    char_u	*str;
+    char_u	buf[NUMBUFLEN];
+
+    str = get_tv_string_buf(&argvars[0], buf);
+    do_py3eval(str, rettv);
+}
+#endif
+
+#ifdef FEAT_PYTHON
+/*
+ * "pyeval()" function
+ */
+    static void
+f_pyeval(argvars, rettv)
+    typval_T	*argvars;
+    typval_T	*rettv;
+{
+    char_u	*str;
+    char_u	buf[NUMBUFLEN];
+
+    str = get_tv_string_buf(&argvars[0], buf);
+    do_pyeval(str, rettv);
+}
+#endif
+
 /*
  * "range()" function
  */
@@ -22139,7 +22196,7 @@ func_free(fp)
  * Unreference a Function: decrement the reference count and free it when it
  * becomes zero.  Only for numbered functions.
  */
-    static void
+    void
 func_unref(name)
     char_u	*name;
 {
@@ -22163,7 +22220,7 @@ func_unref(name)
 /*
  * Count a reference to a Function.
  */
-    static void
+    void
 func_ref(name)
     char_u	*name;
 {
--- a/src/if_lua.c
+++ b/src/if_lua.c
@@ -199,9 +199,9 @@ int (*dll_lua_pcall) (lua_State *L, int 
 lua_Number (*dll_lua_tonumberx) (lua_State *L, int idx, int *isnum);
 lua_Integer (*dll_lua_tointegerx) (lua_State *L, int idx, int *isnum);
 void (*dll_lua_callk) (lua_State *L, int nargs, int nresults, int ctx,
-        lua_CFunction k);
+	lua_CFunction k);
 int (*dll_lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc,
-        int ctx, lua_CFunction k);
+	int ctx, lua_CFunction k);
 void (*dll_lua_getglobal) (lua_State *L, const char *var);
 void (*dll_lua_setglobal) (lua_State *L, const char *var);
 #endif
@@ -394,7 +394,7 @@ lua_enabled(int verbose)
 luaL_typeerror (lua_State *L, int narg, const char *tname)
 {
     const char *msg = lua_pushfstring(L, "%s expected, got %s",
-            tname, luaL_typename(L, narg));
+	    tname, luaL_typename(L, narg));
     return luaL_argerror(L, narg, msg);
 }
 #endif
@@ -646,141 +646,6 @@ luaV_msgfunc(lua_State *L, msgfunc_T mf)
 	return 1; \
     }
 
-
-/* adapted from eval.c */
-
-#define listitem_alloc() (listitem_T *)alloc(sizeof(listitem_T))
-
-    static listitem_T *
-list_find (list_T *l, long n)
-{
-    listitem_T *li;
-    if (l == NULL || n < -l->lv_len || n >= l->lv_len)
-	return NULL;
-    if (n < 0) /* search backward? */
-	for (li = l->lv_last; n < -1; li = li->li_prev)
-	    n++;
-    else /* search forward */
-	for (li = l->lv_first; n > 0; li = li->li_next)
-	    n--;
-    return li;
-}
-
-    static void
-list_remove (list_T *l, listitem_T *li)
-{
-    listwatch_T *lw;
-    --l->lv_len;
-    /* fix watchers */
-    for (lw = l->lv_watch; lw != NULL; lw = lw->lw_next)
-	if (lw->lw_item == li)
-	    lw->lw_item = li->li_next;
-    /* fix list pointers */
-    if (li->li_next == NULL) /* last? */
-	l->lv_last = li->li_prev;
-    else
-	li->li_next->li_prev = li->li_prev;
-    if (li->li_prev == NULL) /* first? */
-	l->lv_first = li->li_next;
-    else
-	li->li_prev->li_next = li->li_next;
-    l->lv_idx_item = NULL;
-}
-
-    static void
-list_append(list_T *l, listitem_T *item)
-{
-    if (l->lv_last == NULL) /* empty list? */
-	l->lv_first = item;
-    else
-	l->lv_last->li_next = item;
-    item->li_prev = l->lv_last;
-    item->li_next = NULL;
-    l->lv_last = item;
-    ++l->lv_len;
-}
-
-    static int
-list_insert_tv(list_T *l, typval_T *tv, listitem_T *item)
-{
-    listitem_T	*ni = listitem_alloc();
-
-    if (ni == NULL)
-	return FAIL;
-    copy_tv(tv, &ni->li_tv);
-    if (item == NULL)
-	list_append(l, ni);
-    else
-    {
-	ni->li_prev = item->li_prev;
-	ni->li_next = item;
-	if (item->li_prev == NULL)
-	{
-	    l->lv_first = ni;
-	    ++l->lv_idx;
-	}
-	else
-	{
-	    item->li_prev->li_next = ni;
-	    l->lv_idx_item = NULL;
-	}
-	item->li_prev = ni;
-	++l->lv_len;
-    }
-    return OK;
-}
-
-/* set references */
-
-static void set_ref_in_tv (typval_T *tv, int copyID);
-
-    static void
-set_ref_in_dict(dict_T *d, int copyID)
-{
-    hashtab_T *ht = &d->dv_hashtab;
-    int n = ht->ht_used;
-    hashitem_T *hi;
-    for (hi = ht->ht_array; n > 0; ++hi)
-	if (!HASHITEM_EMPTY(hi))
-	{
-	    dictitem_T *di = dict_lookup(hi);
-	    set_ref_in_tv(&di->di_tv, copyID);
-	    --n;
-	}
-}
-
-    static void
-set_ref_in_list(list_T *l, int copyID)
-{
-    listitem_T *li;
-    for (li = l->lv_first; li != NULL; li = li->li_next)
-	set_ref_in_tv(&li->li_tv, copyID);
-}
-
-    static void
-set_ref_in_tv(typval_T *tv, int copyID)
-{
-    if (tv->v_type == VAR_LIST)
-    {
-	list_T *l = tv->vval.v_list;
-	if (l != NULL && l->lv_copyID != copyID)
-	{
-	    l->lv_copyID = copyID;
-	    set_ref_in_list(l, copyID);
-	}
-    }
-    else if (tv->v_type == VAR_DICT)
-    {
-	dict_T *d = tv->vval.v_dict;
-	if (d != NULL && d->dv_copyID != copyID)
-	{
-	    d->dv_copyID = copyID;
-	    set_ref_in_dict(d, copyID);
-	}
-    }
-}
-
-
 /* =======   List type   ======= */
 
     static luaV_List *
@@ -876,7 +741,7 @@ luaV_list_newindex (lua_State *L)
     if (li == NULL) return 0;
     if (lua_isnil(L, 3)) /* remove? */
     {
-	list_remove(l, li);
+	list_remove(l, li, li);
 	clear_tv(&li->li_tv);
 	vim_free(li);
     }
@@ -904,8 +769,7 @@ luaV_list_add (lua_State *L)
 	typval_T v;
 	lua_settop(L, 2);
 	luaV_totypval(L, 2, &v);
-	copy_tv(&v, &li->li_tv);
-	list_append(l, li);
+	list_append_tv(l, &v);
     }
     lua_settop(L, 1);
     return 1;
@@ -1682,7 +1546,7 @@ luaV_setref (lua_State *L)
 	    tv.vval.v_dict = (dict_T *) lua_touserdata(L, 4); /* key */
 	}
 	lua_pop(L, 2); /* metatable and value */
-	set_ref_in_tv(&tv, copyID);
+	set_ref_in_item(&tv, copyID);
     }
     return 0;
 }
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -1,4 +1,4 @@
-/* vi:set ts=8 sts=4 sw=4:
+/* vi:set ts=8 sts=4 sw=4 noet:
  *
  * VIM - Vi IMproved	by Bram Moolenaar
  *
@@ -105,7 +105,8 @@ OutputWritelines(PyObject *self, PyObjec
 	return NULL;
     Py_INCREF(list);
 
-    if (!PyList_Check(list)) {
+    if (!PyList_Check(list))
+    {
 	PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
 	Py_DECREF(list);
 	return NULL;
@@ -119,7 +120,8 @@ OutputWritelines(PyObject *self, PyObjec
 	char *str = NULL;
 	PyInt len;
 
-	if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len)) {
+	if (!PyArg_Parse(line, "et#", ENC_OPT, &str, &len))
+	{
 	    PyErr_SetString(PyExc_TypeError, _("writelines() requires list of strings"));
 	    Py_DECREF(list);
 	    return NULL;
@@ -297,7 +299,7 @@ VimToPython(typval_T *our_tv, int depth,
 {
     PyObject	*result;
     PyObject	*newObj;
-    char	ptrBuf[NUMBUFLEN];
+    char	ptrBuf[sizeof(void *) * 2 + 3];
 
     /* Avoid infinite recursion */
     if (depth > 100)
@@ -312,9 +314,9 @@ VimToPython(typval_T *our_tv, int depth,
     if ((our_tv->v_type == VAR_LIST && our_tv->vval.v_list != NULL)
 	    || (our_tv->v_type == VAR_DICT && our_tv->vval.v_dict != NULL))
     {
-	sprintf(ptrBuf, PRINTF_DECIMAL_LONG_U,
-		our_tv->v_type == VAR_LIST ? (long_u)our_tv->vval.v_list
-					   : (long_u)our_tv->vval.v_dict);
+	sprintf(ptrBuf, "%p",
+		our_tv->v_type == VAR_LIST ? (void *)our_tv->vval.v_list
+					   : (void *)our_tv->vval.v_dict);
 	result = PyDict_GetItemString(lookupDict, ptrBuf);
 	if (result != NULL)
 	{
@@ -445,6 +447,57 @@ VimEval(PyObject *self UNUSED, PyObject 
 #endif
 }
 
+static PyObject *ConvertToPyObject(typval_T *);
+
+    static PyObject *
+VimEvalPy(PyObject *self UNUSED, PyObject *args UNUSED)
+{
+#ifdef FEAT_EVAL
+    char	*expr;
+    typval_T	*our_tv;
+    PyObject	*result;
+
+    if (!PyArg_ParseTuple(args, "s", &expr))
+	return NULL;
+
+    Py_BEGIN_ALLOW_THREADS
+    Python_Lock_Vim();
+    our_tv = eval_expr((char_u *)expr, NULL);
+
+    Python_Release_Vim();
+    Py_END_ALLOW_THREADS
+
+    if (our_tv == NULL)
+    {
+	PyErr_SetVim(_("invalid expression"));
+	return NULL;
+    }
+
+    result = ConvertToPyObject(our_tv);
+    Py_BEGIN_ALLOW_THREADS
+    Python_Lock_Vim();
+    free_tv(our_tv);
+    Python_Release_Vim();
+    Py_END_ALLOW_THREADS
+
+    return result;
+#else
+    PyErr_SetVim(_("expressions disabled at compile time"));
+    return NULL;
+#endif
+}
+
+    static PyObject *
+VimStrwidth(PyObject *self UNUSED, PyObject *args)
+{
+    char	*expr;
+
+    if (!PyArg_ParseTuple(args, "s", &expr))
+	return NULL;
+
+    return PyLong_FromLong(mb_string2cells((char_u *)expr, STRLEN(expr)));
+}
+
 /*
  * Vim module - Definitions
  */
@@ -453,6 +506,8 @@ static struct PyMethodDef VimMethods[] =
     /* name,	     function,		calling,    documentation */
     {"command",	     VimCommand,	1,	    "Execute a Vim ex-mode command" },
     {"eval",	     VimEval,		1,	    "Evaluate an expression using Vim evaluator" },
+    {"bindeval",     VimEvalPy,         1,          "Like eval(), but returns objects attached to vim ones"},
+    {"strwidth",     VimStrwidth,       1,          "Screen string width, counts <Tab> as having width 1"},
     { NULL,	     NULL,		0,	    NULL }
 };
 
@@ -460,8 +515,7 @@ typedef struct
 {
     PyObject_HEAD
     buf_T *buf;
-}
-BufferObject;
+} BufferObject;
 
 #define INVALID_BUFFER_VALUE ((buf_T *)(-1))
 
@@ -505,6 +559,768 @@ typedef struct
     win_T	*win;
 } WindowObject;
 
+static int ConvertFromPyObject(PyObject *, typval_T *);
+static int _ConvertFromPyObject(PyObject *, typval_T *, PyObject *);
+
+typedef struct pylinkedlist_S {
+    struct pylinkedlist_S	*pll_next;
+    struct pylinkedlist_S	*pll_prev;
+    PyObject			*pll_obj;
+} pylinkedlist_T;
+
+static pylinkedlist_T *lastdict = NULL;
+static pylinkedlist_T *lastlist = NULL;
+
+    static void
+pyll_remove(pylinkedlist_T *ref, pylinkedlist_T **last)
+{
+    if (ref->pll_prev == NULL)
+    {
+	if (ref->pll_next == NULL)
+	{
+	    *last = NULL;
+	    return;
+	}
+    }
+    else
+	ref->pll_prev->pll_next = ref->pll_next;
+
+    if (ref->pll_next == NULL)
+	*last = ref->pll_prev;
+    else
+	ref->pll_next->pll_prev = ref->pll_prev;
+}
+
+    static void
+pyll_add(PyObject *self, pylinkedlist_T *ref, pylinkedlist_T **last)
+{
+    if (*last == NULL)
+	ref->pll_prev = NULL;
+    else
+    {
+	(*last)->pll_next = ref;
+	ref->pll_prev = *last;
+    }
+    ref->pll_next = NULL;
+    ref->pll_obj = self;
+    *last = ref;
+}
+
+static PyTypeObject DictionaryType;
+
+typedef struct
+{
+    PyObject_HEAD
+    dict_T	*dict;
+    pylinkedlist_T	ref;
+} DictionaryObject;
+
+    static PyObject *
+DictionaryNew(dict_T *dict)
+{
+    DictionaryObject	*self;
+
+    self = PyObject_NEW(DictionaryObject, &DictionaryType);
+    if (self == NULL)
+	return NULL;
+    self->dict = dict;
+    ++dict->dv_refcount;
+
+    pyll_add((PyObject *)(self), &self->ref, &lastdict);
+
+    return (PyObject *)(self);
+}
+
+    static int
+pydict_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+    dict_T	*d;
+    char_u	*key;
+    dictitem_T	*di;
+    PyObject	*keyObject;
+    PyObject	*valObject;
+    Py_ssize_t	iter = 0;
+
+    d = dict_alloc();
+    if (d == NULL)
+    {
+	PyErr_NoMemory();
+	return -1;
+    }
+
+    tv->v_type = VAR_DICT;
+    tv->vval.v_dict = d;
+
+    while (PyDict_Next(obj, &iter, &keyObject, &valObject))
+    {
+	DICTKEY_DECL
+
+	if (keyObject == NULL)
+	    return -1;
+	if (valObject == NULL)
+	    return -1;
+
+	DICTKEY_GET(-1)
+
+	di = dictitem_alloc(key);
+
+	DICTKEY_UNREF
+
+	if (di == NULL)
+	{
+	    PyErr_NoMemory();
+	    return -1;
+	}
+	di->di_tv.v_lock = 0;
+
+	if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1)
+	{
+	    vim_free(di);
+	    return -1;
+	}
+	if (dict_add(d, di) == FAIL)
+	{
+	    vim_free(di);
+	    PyErr_SetVim(_("failed to add key to dictionary"));
+	    return -1;
+	}
+    }
+    return 0;
+}
+
+    static int
+pymap_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+    dict_T	*d;
+    char_u	*key;
+    dictitem_T	*di;
+    PyObject	*list;
+    PyObject	*litem;
+    PyObject	*keyObject;
+    PyObject	*valObject;
+    Py_ssize_t	lsize;
+
+    d = dict_alloc();
+    if (d == NULL)
+    {
+	PyErr_NoMemory();
+	return -1;
+    }
+
+    tv->v_type = VAR_DICT;
+    tv->vval.v_dict = d;
+
+    list = PyMapping_Items(obj);
+    lsize = PyList_Size(list);
+    while (lsize--)
+    {
+	DICTKEY_DECL
+
+	litem = PyList_GetItem(list, lsize);
+	if (litem == NULL)
+	{
+	    Py_DECREF(list);
+	    return -1;
+	}
+
+	keyObject = PyTuple_GetItem(litem, 0);
+	if (keyObject == NULL)
+	{
+	    Py_DECREF(list);
+	    Py_DECREF(litem);
+	    return -1;
+	}
+
+	DICTKEY_GET(-1)
+
+	valObject = PyTuple_GetItem(litem, 1);
+	if (valObject == NULL)
+	{
+	    Py_DECREF(list);
+	    Py_DECREF(litem);
+	    return -1;
+	}
+
+	di = dictitem_alloc(key);
+
+	DICTKEY_UNREF
+
+	if (di == NULL)
+	{
+	    Py_DECREF(list);
+	    Py_DECREF(litem);
+	    PyErr_NoMemory();
+	    return -1;
+	}
+	di->di_tv.v_lock = 0;
+
+	if (_ConvertFromPyObject(valObject, &di->di_tv, lookupDict) == -1)
+	{
+	    vim_free(di);
+	    Py_DECREF(list);
+	    Py_DECREF(litem);
+	    return -1;
+	}
+	if (dict_add(d, di) == FAIL)
+	{
+	    vim_free(di);
+	    Py_DECREF(list);
+	    Py_DECREF(litem);
+	    PyErr_SetVim(_("failed to add key to dictionary"));
+	    return -1;
+	}
+	Py_DECREF(litem);
+    }
+    Py_DECREF(list);
+    return 0;
+}
+
+    static PyInt
+DictionaryLength(PyObject *self)
+{
+    return ((PyInt) ((((DictionaryObject *)(self))->dict->dv_hashtab.ht_used)));
+}
+
+    static PyObject *
+DictionaryItem(PyObject *self, PyObject *keyObject)
+{
+    char_u	*key;
+    dictitem_T	*val;
+    DICTKEY_DECL
+
+    DICTKEY_GET(NULL)
+
+    val = dict_find(((DictionaryObject *) (self))->dict, key, -1);
+
+    DICTKEY_UNREF
+
+    return ConvertToPyObject(&val->di_tv);
+}
+
+    static PyInt
+DictionaryAssItem(PyObject *self, PyObject *keyObject, PyObject *valObject)
+{
+    char_u	*key;
+    typval_T	tv;
+    dict_T	*d = ((DictionaryObject *)(self))->dict;
+    dictitem_T	*di;
+    DICTKEY_DECL
+
+    if (d->dv_lock)
+    {
+	PyErr_SetVim(_("dict is locked"));
+	return -1;
+    }
+
+    DICTKEY_GET(-1)
+
+    di = dict_find(d, key, -1);
+
+    if (valObject == NULL)
+    {
+	if (di == NULL)
+	{
+	    PyErr_SetString(PyExc_IndexError, _("no such key in dictionary"));
+	    return -1;
+	}
+	hashitem_T	*hi = hash_find(&d->dv_hashtab, di->di_key);
+	hash_remove(&d->dv_hashtab, hi);
+	dictitem_free(di);
+	return 0;
+    }
+
+    if (ConvertFromPyObject(valObject, &tv) == -1)
+    {
+	return -1;
+    }
+
+    if (di == NULL)
+    {
+	di = dictitem_alloc(key);
+	if (di == NULL)
+	{
+	    PyErr_NoMemory();
+	    return -1;
+	}
+	di->di_tv.v_lock = 0;
+
+	if (dict_add(d, di) == FAIL)
+	{
+	    vim_free(di);
+	    PyErr_SetVim(_("failed to add key to dictionary"));
+	    return -1;
+	}
+    }
+    else
+	clear_tv(&di->di_tv);
+
+    DICTKEY_UNREF
+
+    copy_tv(&tv, &di->di_tv);
+    return 0;
+}
+
+    static PyObject *
+DictionaryListKeys(PyObject *self)
+{
+    dict_T	*dict = ((DictionaryObject *)(self))->dict;
+    long_u	todo = dict->dv_hashtab.ht_used;
+    Py_ssize_t	i = 0;
+    PyObject	*r;
+    hashitem_T	*hi;
+
+    r = PyList_New(todo);
+    for (hi = dict->dv_hashtab.ht_array; todo > 0; ++hi)
+    {
+	if (!HASHITEM_EMPTY(hi))
+	{
+	    PyList_SetItem(r, i, PyBytes_FromString((char *)(hi->hi_key)));
+	    --todo;
+	    ++i;
+	}
+    }
+    return r;
+}
+
+static struct PyMethodDef DictionaryMethods[] = {
+    {"keys", (PyCFunction)DictionaryListKeys, METH_NOARGS, ""},
+    { NULL,	    NULL,		0,	    NULL }
+};
+
+static PyTypeObject ListType;
+
+typedef struct
+{
+    PyObject_HEAD
+    list_T	*list;
+    pylinkedlist_T	ref;
+} ListObject;
+
+    static PyObject *
+ListNew(list_T *list)
+{
+    ListObject	*self;
+
+    self = PyObject_NEW(ListObject, &ListType);
+    if (self == NULL)
+	return NULL;
+    self->list = list;
+    ++list->lv_refcount;
+
+    pyll_add((PyObject *)(self), &self->ref, &lastlist);
+
+    return (PyObject *)(self);
+}
+
+    static int
+list_py_concat(list_T *l, PyObject *obj, PyObject *lookupDict)
+{
+    Py_ssize_t	i;
+    Py_ssize_t	lsize = PySequence_Size(obj);
+    PyObject	*litem;
+    listitem_T	*li;
+
+    for(i=0; i<lsize; i++)
+    {
+	li = listitem_alloc();
+	if (li == NULL)
+	{
+	    PyErr_NoMemory();
+	    return -1;
+	}
+	li->li_tv.v_lock = 0;
+
+	litem = PySequence_GetItem(obj, i);
+	if (litem == NULL)
+	    return -1;
+	if (_ConvertFromPyObject(litem, &li->li_tv, lookupDict) == -1)
+	    return -1;
+
+	list_append(l, li);
+    }
+    return 0;
+}
+
+    static int
+pyseq_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+    list_T	*l;
+
+    l = list_alloc();
+    if (l == NULL)
+    {
+	PyErr_NoMemory();
+	return -1;
+    }
+
+    tv->v_type = VAR_LIST;
+    tv->vval.v_list = l;
+
+    if (list_py_concat(l, obj, lookupDict) == -1)
+	return -1;
+
+    return 0;
+}
+
+    static int
+pyiter_to_tv(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+    PyObject	*iterator = PyObject_GetIter(obj);
+    PyObject	*item;
+    list_T	*l;
+    listitem_T	*li;
+
+    l = list_alloc();
+
+    if (l == NULL)
+    {
+	PyErr_NoMemory();
+	return -1;
+    }
+
+    tv->vval.v_list = l;
+    tv->v_type = VAR_LIST;
+
+
+    if (iterator == NULL)
+	return -1;
+
+    while ((item = PyIter_Next(obj)))
+    {
+	li = listitem_alloc();
+	if (li == NULL)
+	{
+	    PyErr_NoMemory();
+	    return -1;
+	}
+	li->li_tv.v_lock = 0;
+
+	if (_ConvertFromPyObject(item, &li->li_tv, lookupDict) == -1)
+	    return -1;
+
+	list_append(l, li);
+
+	Py_DECREF(item);
+    }
+
+    Py_DECREF(iterator);
+    return 0;
+}
+
+    static PyInt
+ListLength(PyObject *self)
+{
+    return ((PyInt) (((ListObject *) (self))->list->lv_len));
+}
+
+    static PyObject *
+ListItem(PyObject *self, Py_ssize_t index)
+{
+    listitem_T	*li;
+
+    if (index>=ListLength(self))
+    {
+	PyErr_SetString(PyExc_IndexError, "list index out of range");
+	return NULL;
+    }
+    li = list_find(((ListObject *) (self))->list, (long) index);
+    if (li == NULL)
+    {
+	PyErr_SetVim(_("internal error: failed to get vim list item"));
+	return NULL;
+    }
+    return ConvertToPyObject(&li->li_tv);
+}
+
+#define PROC_RANGE \
+    if (last < 0) {\
+	if (last < -size) \
+	    last = 0; \
+	else \
+	    last += size; \
+    } \
+    if (first < 0) \
+	first = 0; \
+    if (first > size) \
+	first = size; \
+    if (last > size) \
+	last = size;
+
+    static PyObject *
+ListSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last)
+{
+    PyInt	i;
+    PyInt	size = ListLength(self);
+    PyInt	n;
+    PyObject	*list;
+    int		reversed = 0;
+
+    PROC_RANGE
+    if (first >= last)
+	first = last;
+
+    n = last-first;
+    list = PyList_New(n);
+    if (list == NULL)
+	return NULL;
+
+    for (i = 0; i < n; ++i)
+    {
+	PyObject	*item = ListItem(self, i);
+	if (item == NULL)
+	{
+	    Py_DECREF(list);
+	    return NULL;
+	}
+
+	if ((PyList_SetItem(list, ((reversed)?(n-i-1):(i)), item)))
+	{
+	    Py_DECREF(item);
+	    Py_DECREF(list);
+	    return NULL;
+	}
+    }
+
+    return list;
+}
+
+    static int
+ListAssItem(PyObject *self, Py_ssize_t index, PyObject *obj)
+{
+    typval_T	tv;
+    list_T	*l = ((ListObject *) (self))->list;
+    listitem_T	*li;
+    Py_ssize_t	length = ListLength(self);
+
+    if (l->lv_lock)
+    {
+	PyErr_SetVim(_("list is locked"));
+	return -1;
+    }
+    if (index>length || (index==length && obj==NULL))
+    {
+	PyErr_SetString(PyExc_IndexError, "list index out of range");
+	return -1;
+    }
+
+    if (obj == NULL)
+    {
+	li = list_find(l, (long) index);
+	list_remove(l, li, li);
+	clear_tv(&li->li_tv);
+	vim_free(li);
+	return 0;
+    }
+
+    if (ConvertFromPyObject(obj, &tv) == -1)
+	return -1;
+
+    if (index == length)
+    {
+	if (list_append_tv(l, &tv) == FAIL)
+	{
+	    PyErr_SetVim(_("Failed to add item to list"));
+	    return -1;
+	}
+    }
+    else
+    {
+	li = list_find(l, (long) index);
+	clear_tv(&li->li_tv);
+	copy_tv(&tv, &li->li_tv);
+    }
+    return 0;
+}
+
+    static int
+ListAssSlice(PyObject *self, Py_ssize_t first, Py_ssize_t last, PyObject *obj)
+{
+    PyInt	size = ListLength(self);
+    Py_ssize_t	i;
+    Py_ssize_t	lsize;
+    PyObject	*litem;
+    listitem_T	*li;
+    listitem_T	*next;
+    typval_T	v;
+    list_T	*l = ((ListObject *) (self))->list;
+
+    if (l->lv_lock)
+    {
+	PyErr_SetVim(_("list is locked"));
+	return -1;
+    }
+
+    PROC_RANGE
+
+    if (first == size)
+	li = NULL;
+    else
+    {
+	li = list_find(l, (long) first);
+	if (li == NULL)
+	{
+	    PyErr_SetVim(_("internal error: no vim list item"));
+	    return -1;
+	}
+	if (last > first)
+	{
+	    i = last - first;
+	    while (i-- && li != NULL)
+	    {
+		next = li->li_next;
+		listitem_remove(l, li);
+		li = next;
+	    }
+	}
+    }
+
+    if (obj == NULL)
+	return 0;
+
+    if (!PyList_Check(obj))
+    {
+	PyErr_SetString(PyExc_TypeError, _("can only assign lists to slice"));
+	return -1;
+    }
+
+    lsize = PyList_Size(obj);
+
+    for(i=0; i<lsize; i++)
+    {
+	litem = PyList_GetItem(obj, i);
+	if (litem == NULL)
+	    return -1;
+	if (ConvertFromPyObject(litem, &v) == -1)
+	    return -1;
+	if (list_insert_tv(l, &v, li) == FAIL)
+	{
+	    PyErr_SetVim(_("internal error: failed to add item to list"));
+	    return -1;
+	}
+    }
+    return 0;
+}
+
+    static PyObject *
+ListConcatInPlace(PyObject *self, PyObject *obj)
+{
+    list_T	*l = ((ListObject *) (self))->list;
+    PyObject	*lookup_dict;
+
+    if (l->lv_lock)
+    {
+	PyErr_SetVim(_("list is locked"));
+	return NULL;
+    }
+
+    if (!PySequence_Check(obj))
+    {
+	PyErr_SetString(PyExc_TypeError, _("can only concatenate with lists"));
+	return NULL;
+    }
+
+    lookup_dict = PyDict_New();
+    if (list_py_concat(l, obj, lookup_dict) == -1)
+    {
+	Py_DECREF(lookup_dict);
+	return NULL;
+    }
+    Py_DECREF(lookup_dict);
+
+    Py_INCREF(self);
+    return self;
+}
+
+static struct PyMethodDef ListMethods[] = {
+    {"extend", (PyCFunction)ListConcatInPlace, METH_O, ""},
+    { NULL,	    NULL,		0,	    NULL }
+};
+
+typedef struct
+{
+    PyObject_HEAD
+    char_u	*name;
+} FunctionObject;
+
+static PyTypeObject FunctionType;
+
+    static PyObject *
+FunctionNew(char_u *name)
+{
+    FunctionObject	*self;
+
+    self = PyObject_NEW(FunctionObject, &FunctionType);
+    if (self == NULL)
+	return NULL;
+    self->name = PyMem_New(char_u, STRLEN(name) + 1);
+    if (self->name == NULL)
+    {
+	PyErr_NoMemory();
+	return NULL;
+    }
+    STRCPY(self->name, name);
+    func_ref(name);
+    return (PyObject *)(self);
+}
+
+    static PyObject *
+FunctionCall(PyObject *self, PyObject *argsObject, PyObject *kwargs)
+{
+    FunctionObject	*this = (FunctionObject *)(self);
+    char_u	*name = this->name;
+    typval_T	args;
+    typval_T	selfdicttv;
+    typval_T	rettv;
+    dict_T	*selfdict = NULL;
+    PyObject	*selfdictObject;
+    PyObject	*result;
+    int		error;
+
+    if (ConvertFromPyObject(argsObject, &args) == -1)
+	return NULL;
+
+    if (kwargs != NULL)
+    {
+	selfdictObject = PyDict_GetItemString(kwargs, "self");
+	if (selfdictObject != NULL)
+	{
+	    if (!PyDict_Check(selfdictObject))
+	    {
+		PyErr_SetString(PyExc_TypeError, _("'self' argument must be a dictionary"));
+		clear_tv(&args);
+		return NULL;
+	    }
+	    if (ConvertFromPyObject(selfdictObject, &selfdicttv) == -1)
+		return NULL;
+	    selfdict = selfdicttv.vval.v_dict;
+	}
+    }
+
+    error = func_call(name, &args, selfdict, &rettv);
+    if (error != OK)
+    {
+	result = NULL;
+	PyErr_SetVim(_("failed to run function"));
+    }
+    else
+	result = ConvertToPyObject(&rettv);
+
+    /* FIXME Check what should really be cleared. */
+    clear_tv(&args);
+    clear_tv(&rettv);
+    /*
+     * if (selfdict!=NULL)
+     *     clear_tv(selfdicttv);
+     */
+
+    return result;
+}
+
+static struct PyMethodDef FunctionMethods[] = {
+    {"__call__",    (PyCFunction)FunctionCall, METH_VARARGS|METH_KEYWORDS, ""},
+    { NULL,	    NULL,		0,	    NULL }
+};
+
 #define INVALID_WINDOW_VALUE ((win_T *)(-1))
 
     static int
@@ -1567,3 +2383,256 @@ static struct PyMethodDef RangeMethods[]
     { NULL,	    NULL,		0,	    NULL }
 };
 
+    static void
+set_ref_in_py(const int copyID)
+{
+    pylinkedlist_T	*cur;
+    dict_T	*dd;
+    list_T	*ll;
+
+    if (lastdict != NULL)
+	for(cur = lastdict ; cur != NULL ; cur = cur->pll_prev)
+	{
+	    dd = ((DictionaryObject *) (cur->pll_obj))->dict;
+	    if (dd->dv_copyID != copyID)
+	    {
+		dd->dv_copyID = copyID;
+		set_ref_in_ht(&dd->dv_hashtab, copyID);
+	    }
+	}
+
+    if (lastlist != NULL)
+	for(cur = lastlist ; cur != NULL ; cur = cur->pll_prev)
+	{
+	    ll = ((ListObject *) (cur->pll_obj))->list;
+	    if (ll->lv_copyID != copyID)
+	    {
+		ll->lv_copyID = copyID;
+		set_ref_in_list(ll, copyID);
+	    }
+	}
+}
+
+    static int
+set_string_copy(char_u *str, typval_T *tv)
+{
+    tv->vval.v_string = vim_strsave(str);
+    if (tv->vval.v_string == NULL)
+    {
+	PyErr_NoMemory();
+	return -1;
+    }
+    return 0;
+}
+
+#ifdef FEAT_EVAL
+typedef int (*pytotvfunc)(PyObject *, typval_T *, PyObject *);
+
+    static int
+convert_dl(PyObject *obj, typval_T *tv,
+				    pytotvfunc py_to_tv, PyObject *lookupDict)
+{
+    PyObject	*capsule;
+    char	hexBuf[sizeof(void *) * 2 + 3];
+
+    sprintf(hexBuf, "%p", obj);
+
+    capsule = PyDict_GetItemString(lookupDict, hexBuf);
+    if (capsule == NULL)
+    {
+	capsule = PyCapsule_New(tv, NULL, NULL);
+	PyDict_SetItemString(lookupDict, hexBuf, capsule);
+	Py_DECREF(capsule);
+	if (py_to_tv(obj, tv, lookupDict) == -1)
+	{
+	    tv->v_type = VAR_UNKNOWN;
+	    return -1;
+	}
+	/* As we are not using copy_tv which increments reference count we must
+	 * do it ourself. */
+	switch(tv->v_type)
+	{
+	    case VAR_DICT: ++tv->vval.v_dict->dv_refcount; break;
+	    case VAR_LIST: ++tv->vval.v_list->lv_refcount; break;
+	}
+    }
+    else
+    {
+	typval_T	*v = PyCapsule_GetPointer(capsule, NULL);
+	copy_tv(v, tv);
+    }
+    return 0;
+}
+
+    static int
+ConvertFromPyObject(PyObject *obj, typval_T *tv)
+{
+    PyObject	*lookup_dict;
+    int		r;
+
+    lookup_dict = PyDict_New();
+    r = _ConvertFromPyObject(obj, tv, lookup_dict);
+    Py_DECREF(lookup_dict);
+    return r;
+}
+
+    static int
+_ConvertFromPyObject(PyObject *obj, typval_T *tv, PyObject *lookupDict)
+{
+    if (obj->ob_type == &DictionaryType)
+    {
+	tv->v_type = VAR_DICT;
+	tv->vval.v_dict = (((DictionaryObject *)(obj))->dict);
+	++tv->vval.v_dict->dv_refcount;
+    }
+    else if (obj->ob_type == &ListType)
+    {
+	tv->v_type = VAR_LIST;
+	tv->vval.v_list = (((ListObject *)(obj))->list);
+	++tv->vval.v_list->lv_refcount;
+    }
+    else if (obj->ob_type == &FunctionType)
+    {
+	if (set_string_copy(((FunctionObject *) (obj))->name, tv) == -1)
+	    return -1;
+
+	tv->v_type = VAR_FUNC;
+	func_ref(tv->vval.v_string);
+    }
+#if PY_MAJOR_VERSION >= 3
+    else if (PyBytes_Check(obj))
+    {
+	char_u	*result = (char_u *) PyBytes_AsString(obj);
+
+	if (result == NULL)
+	    return -1;
+
+	if (set_string_copy(result, tv) == -1)
+	    return -1;
+
+	tv->v_type = VAR_STRING;
+    }
+    else if (PyUnicode_Check(obj))
+    {
+	PyObject	*bytes;
+	char_u	*result;
+
+	bytes = PyString_AsBytes(obj);
+	if (bytes == NULL)
+	    return -1;
+
+	result = (char_u *) PyBytes_AsString(bytes);
+	if (result == NULL)
+	    return -1;
+
+	if (set_string_copy(result, tv) == -1)
+	{
+	    Py_XDECREF(bytes);
+	    return -1;
+	}
+	Py_XDECREF(bytes);
+
+	tv->v_type = VAR_STRING;
+    }
+#else
+    else if (PyUnicode_Check(obj))
+    {
+	PyObject	*bytes;
+	char_u	*result;
+
+	bytes = PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, NULL);
+	if (bytes == NULL)
+	    return -1;
+
+	result=(char_u *) PyString_AsString(bytes);
+	if (result == NULL)
+	    return -1;
+
+	if (set_string_copy(result, tv) == -1)
+	{
+	    Py_XDECREF(bytes);
+	    return -1;
+	}
+	Py_XDECREF(bytes);
+
+	tv->v_type = VAR_STRING;
+    }
+    else if (PyString_Check(obj))
+    {
+	char_u	*result = (char_u *) PyString_AsString(obj);
+
+	if (result == NULL)
+	    return -1;
+
+	if (set_string_copy(result, tv) == -1)
+	    return -1;
+
+	tv->v_type = VAR_STRING;
+    }
+    else if (PyInt_Check(obj))
+    {
+	tv->v_type = VAR_NUMBER;
+	tv->vval.v_number = (varnumber_T) PyInt_AsLong(obj);
+    }
+#endif
+    else if (PyLong_Check(obj))
+    {
+	tv->v_type = VAR_NUMBER;
+	tv->vval.v_number = (varnumber_T) PyLong_AsLong(obj);
+    }
+    else if (PyDict_Check(obj))
+	return convert_dl(obj, tv, pydict_to_tv, lookupDict);
+#ifdef FEAT_FLOAT
+    else if (PyFloat_Check(obj))
+    {
+	tv->v_type = VAR_FLOAT;
+	tv->vval.v_float = (float_T) PyFloat_AsDouble(obj);
+    }
+#endif
+    else if (PyIter_Check(obj))
+	return convert_dl(obj, tv, pyiter_to_tv, lookupDict);
+    else if (PySequence_Check(obj))
+	return convert_dl(obj, tv, pyseq_to_tv, lookupDict);
+    else if (PyMapping_Check(obj))
+	return convert_dl(obj, tv, pymap_to_tv, lookupDict);
+    else
+    {
+	PyErr_SetString(PyExc_TypeError, _("unable to convert to vim structure"));
+	return -1;
+    }
+    return 0;
+}
+
+    static PyObject *
+ConvertToPyObject(typval_T *tv)
+{
+    if (tv == NULL)
+    {
+	PyErr_SetVim(_("NULL reference passed"));
+	return NULL;
+    }
+    switch (tv->v_type)
+    {
+	case VAR_STRING:
+	    return PyBytes_FromString((char *) tv->vval.v_string);
+	case VAR_NUMBER:
+	    return PyLong_FromLong((long) tv->vval.v_number);
+#ifdef FEAT_FLOAT
+	case VAR_FLOAT:
+	    return PyFloat_FromDouble((double) tv->vval.v_float);
+#endif
+	case VAR_LIST:
+	    return ListNew(tv->vval.v_list);
+	case VAR_DICT:
+	    return DictionaryNew(tv->vval.v_dict);
+	case VAR_FUNC:
+	    return FunctionNew(tv->vval.v_string);
+	case VAR_UNKNOWN:
+	    Py_INCREF(Py_None);
+	    return Py_None;
+	default:
+	    PyErr_SetVim(_("internal error: invalid value type"));
+	    return NULL;
+    }
+}
+#endif
--- a/src/if_python.c
+++ b/src/if_python.c
@@ -1,4 +1,4 @@
-/* vi:set ts=8 sts=4 sw=4:
+/* vi:set ts=8 sts=4 sw=4 noet:
  *
  * VIM - Vi IMproved	by Bram Moolenaar
  *
@@ -56,6 +56,8 @@
 
 static void init_structs(void);
 
+#define PyBytes_FromString PyString_FromString
+
 /* No-op conversion functions, use with care! */
 #define PyString_AsBytes(obj) (obj)
 #define PyString_FreeBytes(obj)
@@ -122,11 +124,13 @@ struct PyMethodDef { Py_ssize_t a; };
 /* This makes if_python.c compile without warnings against Python 2.5
  * on Win32 and Win64. */
 # undef PyRun_SimpleString
+# undef PyRun_String
 # undef PyArg_Parse
 # undef PyArg_ParseTuple
 # undef Py_BuildValue
 # undef Py_InitModule4
 # undef Py_InitModule4_64
+# undef PyObject_CallMethod
 
 /*
  * Wrapper defines
@@ -134,6 +138,7 @@ struct PyMethodDef { Py_ssize_t a; };
 # define PyArg_Parse dll_PyArg_Parse
 # define PyArg_ParseTuple dll_PyArg_ParseTuple
 # define PyMem_Free dll_PyMem_Free
+# define PyMem_Malloc dll_PyMem_Malloc
 # define PyDict_SetItemString dll_PyDict_SetItemString
 # define PyErr_BadArgument dll_PyErr_BadArgument
 # define PyErr_Clear dll_PyErr_Clear
@@ -150,23 +155,48 @@ struct PyMethodDef { Py_ssize_t a; };
 # endif
 # define PyInt_AsLong dll_PyInt_AsLong
 # define PyInt_FromLong dll_PyInt_FromLong
+# define PyLong_AsLong dll_PyLong_AsLong
+# define PyLong_FromLong dll_PyLong_FromLong
 # define PyInt_Type (*dll_PyInt_Type)
+# define PyLong_Type (*dll_PyLong_Type)
 # define PyList_GetItem dll_PyList_GetItem
 # define PyList_Append dll_PyList_Append
 # define PyList_New dll_PyList_New
 # define PyList_SetItem dll_PyList_SetItem
 # define PyList_Size dll_PyList_Size
 # define PyList_Type (*dll_PyList_Type)
+# define PySequence_Check dll_PySequence_Check
+# define PySequence_Size dll_PySequence_Size
+# define PySequence_GetItem dll_PySequence_GetItem
+# define PyTuple_Size dll_PyTuple_Size
+# define PyTuple_GetItem dll_PyTuple_GetItem
+# define PyTuple_Type (*dll_PyTuple_Type)
 # define PyImport_ImportModule dll_PyImport_ImportModule
 # define PyDict_New dll_PyDict_New
 # define PyDict_GetItemString dll_PyDict_GetItemString
+# define PyDict_Next dll_PyDict_Next
+# ifdef PyMapping_Items
+#  define PY_NO_MAPPING_ITEMS
+# else
+#  define PyMapping_Items dll_PyMapping_Items
+# endif
+# define PyObject_CallMethod dll_PyObject_CallMethod
+# define PyMapping_Check dll_PyMapping_Check
+# define PyIter_Next dll_PyIter_Next
 # define PyModule_GetDict dll_PyModule_GetDict
 # define PyRun_SimpleString dll_PyRun_SimpleString
+# define PyRun_String dll_PyRun_String
 # define PyString_AsString dll_PyString_AsString
 # define PyString_FromString dll_PyString_FromString
 # define PyString_FromStringAndSize dll_PyString_FromStringAndSize
 # define PyString_Size dll_PyString_Size
 # define PyString_Type (*dll_PyString_Type)
+# define PyUnicode_Type (*dll_PyUnicode_Type)
+# define PyUnicodeUCS4_AsEncodedString (*dll_PyUnicodeUCS4_AsEncodedString)
+# define PyFloat_AsDouble dll_PyFloat_AsDouble
+# define PyFloat_FromDouble dll_PyFloat_FromDouble
+# define PyFloat_Type (*dll_PyFloat_Type)
+# define PyImport_AddModule (*dll_PyImport_AddModule)
 # define PySys_SetObject dll_PySys_SetObject
 # define PySys_SetArgv dll_PySys_SetArgv
 # define PyType_Type (*dll_PyType_Type)
@@ -179,8 +209,10 @@ struct PyMethodDef { Py_ssize_t a; };
 # define Py_Finalize dll_Py_Finalize
 # define Py_IsInitialized dll_Py_IsInitialized
 # define _PyObject_New dll__PyObject_New
+# define _PyObject_NextNotImplemented (*dll__PyObject_NextNotImplemented)
 # define _Py_NoneStruct (*dll__Py_NoneStruct)
 # define PyObject_Init dll__PyObject_Init
+# define PyObject_GetIter dll_PyObject_GetIter
 # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
 #  define PyType_IsSubtype dll_PyType_IsSubtype
 # endif
@@ -188,6 +220,8 @@ struct PyMethodDef { Py_ssize_t a; };
 #  define PyObject_Malloc dll_PyObject_Malloc
 #  define PyObject_Free dll_PyObject_Free
 # endif
+# define PyCapsule_New dll_PyCapsule_New
+# define PyCapsule_GetPointer dll_PyCapsule_GetPointer
 
 /*
  * Pointers for dynamic link
@@ -195,6 +229,7 @@ struct PyMethodDef { Py_ssize_t a; };
 static int(*dll_PyArg_Parse)(PyObject *, char *, ...);
 static int(*dll_PyArg_ParseTuple)(PyObject *, char *, ...);
 static int(*dll_PyMem_Free)(void *);
+static void* (*dll_PyMem_Malloc)(size_t);
 static int(*dll_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
 static int(*dll_PyErr_BadArgument)(void);
 static void(*dll_PyErr_Clear)(void);
@@ -208,26 +243,48 @@ static PyThreadState*(*dll_PyEval_SaveTh
 # ifdef PY_CAN_RECURSE
 static PyGILState_STATE	(*dll_PyGILState_Ensure)(void);
 static void (*dll_PyGILState_Release)(PyGILState_STATE);
-#endif
+# endif
 static long(*dll_PyInt_AsLong)(PyObject *);
 static PyObject*(*dll_PyInt_FromLong)(long);
+static long(*dll_PyLong_AsLong)(PyObject *);
+static PyObject*(*dll_PyLong_FromLong)(long);
 static PyTypeObject* dll_PyInt_Type;
+static PyTypeObject* dll_PyLong_Type;
 static PyObject*(*dll_PyList_GetItem)(PyObject *, PyInt);
 static PyObject*(*dll_PyList_Append)(PyObject *, PyObject *);
 static PyObject*(*dll_PyList_New)(PyInt size);
 static int(*dll_PyList_SetItem)(PyObject *, PyInt, PyObject *);
 static PyInt(*dll_PyList_Size)(PyObject *);
 static PyTypeObject* dll_PyList_Type;
+static int (*dll_PySequence_Check)(PyObject *);
+static PyInt(*dll_PySequence_Size)(PyObject *);
+static PyObject*(*dll_PySequence_GetItem)(PyObject *, PyInt);
+static PyInt(*dll_PyTuple_Size)(PyObject *);
+static PyObject*(*dll_PyTuple_GetItem)(PyObject *, PyInt);
+static PyTypeObject* dll_PyTuple_Type;
 static PyObject*(*dll_PyImport_ImportModule)(const char *);
 static PyObject*(*dll_PyDict_New)(void);
 static PyObject*(*dll_PyDict_GetItemString)(PyObject *, const char *);
+static int (*dll_PyDict_Next)(PyObject *, Py_ssize_t *, PyObject **, PyObject **);
+# ifndef PY_NO_MAPPING_ITEMS
+static PyObject* (*dll_PyMapping_Items)(PyObject *);
+# endif
+static PyObject* (*dll_PyObject_CallMethod)(PyObject *, char *, PyObject *);
+static int (*dll_PyMapping_Check)(PyObject *);
+static PyObject* (*dll_PyIter_Next)(PyObject *);
 static PyObject*(*dll_PyModule_GetDict)(PyObject *);
 static int(*dll_PyRun_SimpleString)(char *);
+static PyObject *(*dll_PyRun_String)(char *, int, PyObject *, PyObject *);
 static char*(*dll_PyString_AsString)(PyObject *);
 static PyObject*(*dll_PyString_FromString)(const char *);
 static PyObject*(*dll_PyString_FromStringAndSize)(const char *, PyInt);
 static PyInt(*dll_PyString_Size)(PyObject *);
 static PyTypeObject* dll_PyString_Type;
+static PyTypeObject* dll_PyUnicode_Type;
+static PyObject *(*PyUnicodeUCS4_AsEncodedString)(PyObject *, char *, char *);
+static double(*dll_PyFloat_AsDouble)(PyObject *);
+static PyObject*(*dll_PyFloat_FromDouble)(double);
+static PyTypeObject* dll_PyFloat_Type;
 static int(*dll_PySys_SetObject)(char *, PyObject *);
 static int(*dll_PySys_SetArgv)(int, char **);
 static PyTypeObject* dll_PyType_Type;
@@ -235,12 +292,15 @@ static int (*dll_PyType_Ready)(PyTypeObj
 static PyObject*(*dll_Py_BuildValue)(char *, ...);
 static PyObject*(*dll_Py_FindMethod)(struct PyMethodDef[], PyObject *, char *);
 static PyObject*(*dll_Py_InitModule4)(char *, struct PyMethodDef *, char *, PyObject *, int);
+static PyObject*(*dll_PyImport_AddModule)(char *);
 static void(*dll_Py_SetPythonHome)(char *home);
 static void(*dll_Py_Initialize)(void);
 static void(*dll_Py_Finalize)(void);
 static int(*dll_Py_IsInitialized)(void);
 static PyObject*(*dll__PyObject_New)(PyTypeObject *, PyObject *);
 static PyObject*(*dll__PyObject_Init)(PyObject *, PyTypeObject *);
+static PyObject* (*dll_PyObject_GetIter)(PyObject *);
+static iternextfunc dll__PyObject_NextNotImplemented;
 static PyObject* dll__Py_NoneStruct;
 # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
 static int (*dll_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
@@ -249,6 +309,8 @@ static int (*dll_PyType_IsSubtype)(PyTyp
 static void* (*dll_PyObject_Malloc)(size_t);
 static void (*dll_PyObject_Free)(void*);
 # endif
+static PyObject* (*dll_PyCapsule_New)(void *, char *, PyCapsule_Destructor);
+static void* (*dll_PyCapsule_GetPointer)(PyObject *, char *);
 
 static HINSTANCE hinstPython = 0; /* Instance of python.dll */
 
@@ -278,6 +340,7 @@ static struct
     {"PyArg_Parse", (PYTHON_PROC*)&dll_PyArg_Parse},
     {"PyArg_ParseTuple", (PYTHON_PROC*)&dll_PyArg_ParseTuple},
     {"PyMem_Free", (PYTHON_PROC*)&dll_PyMem_Free},
+    {"PyMem_Malloc", (PYTHON_PROC*)&dll_PyMem_Malloc},
     {"PyDict_SetItemString", (PYTHON_PROC*)&dll_PyDict_SetItemString},
     {"PyErr_BadArgument", (PYTHON_PROC*)&dll_PyErr_BadArgument},
     {"PyErr_Clear", (PYTHON_PROC*)&dll_PyErr_Clear},
@@ -294,23 +357,46 @@ static struct
 # endif
     {"PyInt_AsLong", (PYTHON_PROC*)&dll_PyInt_AsLong},
     {"PyInt_FromLong", (PYTHON_PROC*)&dll_PyInt_FromLong},
+    {"PyLong_AsLong", (PYTHON_PROC*)&dll_PyLong_AsLong},
+    {"PyLong_FromLong", (PYTHON_PROC*)&dll_PyLong_FromLong},
     {"PyInt_Type", (PYTHON_PROC*)&dll_PyInt_Type},
+    {"PyLong_Type", (PYTHON_PROC*)&dll_PyLong_Type},
     {"PyList_GetItem", (PYTHON_PROC*)&dll_PyList_GetItem},
     {"PyList_Append", (PYTHON_PROC*)&dll_PyList_Append},
     {"PyList_New", (PYTHON_PROC*)&dll_PyList_New},
     {"PyList_SetItem", (PYTHON_PROC*)&dll_PyList_SetItem},
     {"PyList_Size", (PYTHON_PROC*)&dll_PyList_Size},
     {"PyList_Type", (PYTHON_PROC*)&dll_PyList_Type},
+    {"PySequence_GetItem", (PYTHON_PROC*)&dll_PySequence_GetItem},
+    {"PySequence_Size", (PYTHON_PROC*)&dll_PySequence_Size},
+    {"PySequence_Check", (PYTHON_PROC*)&dll_PySequence_Check},
+    {"PyTuple_GetItem", (PYTHON_PROC*)&dll_PyTuple_GetItem},
+    {"PyTuple_Size", (PYTHON_PROC*)&dll_PyTuple_Size},
+    {"PyTuple_Type", (PYTHON_PROC*)&dll_PyTuple_Type},
     {"PyImport_ImportModule", (PYTHON_PROC*)&dll_PyImport_ImportModule},
     {"PyDict_GetItemString", (PYTHON_PROC*)&dll_PyDict_GetItemString},
+    {"PyDict_Next", (PYTHON_PROC*)&dll_PyDict_Next},
     {"PyDict_New", (PYTHON_PROC*)&dll_PyDict_New},
+# ifndef PY_NO_MAPPING_ITEMS
+    {"PyMapping_Items", (PYTHON_PROC*)&dll_PyMapping_Items},
+# endif
+    {"PyObject_CallMethod", (PYTHON_PROC*)&dll_PyObject_CallMethod},
+    {"PyMapping_Check", (PYTHON_PROC*)&dll_PyMapping_Check},
+    {"PyIter_Next", (PYTHON_PROC*)&dll_PyIter_Next},
     {"PyModule_GetDict", (PYTHON_PROC*)&dll_PyModule_GetDict},
     {"PyRun_SimpleString", (PYTHON_PROC*)&dll_PyRun_SimpleString},
+    {"PyRun_String", (PYTHON_PROC*)&dll_PyRun_String},
     {"PyString_AsString", (PYTHON_PROC*)&dll_PyString_AsString},
     {"PyString_FromString", (PYTHON_PROC*)&dll_PyString_FromString},
     {"PyString_FromStringAndSize", (PYTHON_PROC*)&dll_PyString_FromStringAndSize},
     {"PyString_Size", (PYTHON_PROC*)&dll_PyString_Size},
     {"PyString_Type", (PYTHON_PROC*)&dll_PyString_Type},
+    {"PyUnicode_Type", (PYTHON_PROC*)&dll_PyUnicode_Type},
+    {"PyUnicodeUCS4_AsEncodedString", (PYTHON_PROC*)&dll_PyUnicodeUCS4_AsEncodedString},
+    {"PyFloat_Type", (PYTHON_PROC*)&dll_PyFloat_Type},
+    {"PyFloat_AsDouble", (PYTHON_PROC*)&dll_PyFloat_AsDouble},
+    {"PyFloat_FromDouble", (PYTHON_PROC*)&dll_PyFloat_FromDouble},
+    {"PyImport_AddModule", (PYTHON_PROC*)&dll_PyImport_AddModule},
     {"PySys_SetObject", (PYTHON_PROC*)&dll_PySys_SetObject},
     {"PySys_SetArgv", (PYTHON_PROC*)&dll_PySys_SetArgv},
     {"PyType_Type", (PYTHON_PROC*)&dll_PyType_Type},
@@ -328,6 +414,8 @@ static struct
     {"Py_IsInitialized", (PYTHON_PROC*)&dll_Py_IsInitialized},
     {"_PyObject_New", (PYTHON_PROC*)&dll__PyObject_New},
     {"PyObject_Init", (PYTHON_PROC*)&dll__PyObject_Init},
+    {"PyObject_GetIter", (PYTHON_PROC*)&dll_PyObject_GetIter},
+    {"_PyObject_NextNotImplemented", (PYTHON_PROC*)&dll__PyObject_NextNotImplemented},
     {"_Py_NoneStruct", (PYTHON_PROC*)&dll__Py_NoneStruct},
 # if defined(PY_VERSION_HEX) && PY_VERSION_HEX >= 0x02020000
     {"PyType_IsSubtype", (PYTHON_PROC*)&dll_PyType_IsSubtype},
@@ -336,6 +424,8 @@ static struct
     {"PyObject_Malloc", (PYTHON_PROC*)&dll_PyObject_Malloc},
     {"PyObject_Free", (PYTHON_PROC*)&dll_PyObject_Free},
 # endif
+    {"PyCapsule_New", (PYTHON_PROC*)&dll_PyCapsule_New},
+    {"PyCapsule_GetPointer", (PYTHON_PROC*)&dll_PyCapsule_GetPointer},
     {"", NULL},
 };
 
@@ -434,10 +524,25 @@ get_exceptions(void)
 
 static PyObject *BufferNew (buf_T *);
 static PyObject *WindowNew(win_T *);
+static PyObject *DictionaryNew(dict_T *);
 static PyObject *LineToString(const char *);
 
 static PyTypeObject RangeType;
 
+static int initialised = 0;
+#define PYINITIALISED initialised
+
+/* Add conversion from PyInt? */
+#define DICTKEY_GET(err) \
+    if (!PyString_Check(keyObject)) \
+    { \
+	PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \
+	return err; \
+    } \
+    key = (char_u *) PyString_AsString(keyObject);
+#define DICTKEY_UNREF
+#define DICTKEY_DECL
+
 /*
  * Include the code shared with if_python3.c
  */
@@ -451,6 +556,8 @@ static PyTypeObject RangeType;
 static PyInt RangeStart;
 static PyInt RangeEnd;
 
+static PyObject *globals;
+
 static void PythonIO_Flush(void);
 static int PythonIO_Init(void);
 static int PythonMod_Init(void);
@@ -466,8 +573,6 @@ static int SetBufferLineList(buf_T *, Py
  * 1. Python interpreter main program.
  */
 
-static int initialised = 0;
-
 #if PYTHON_API_VERSION < 1007 /* Python 1.4 */
 typedef PyObject PyThreadState;
 #endif
@@ -581,6 +686,8 @@ Python_Init(void)
 	if (PythonMod_Init())
 	    goto fail;
 
+	globals = PyModule_GetDict(PyImport_AddModule("__main__"));
+
 	/* Remove the element from sys.path that was added because of our
 	 * argv[0] value in PythonMod_Init().  Previously we used an empty
 	 * string, but dependinding on the OS we then get an empty entry or
@@ -609,7 +716,7 @@ fail:
  * External interface
  */
     static void
-DoPythonCommand(exarg_T *eap, const char *cmd)
+DoPythonCommand(exarg_T *eap, const char *cmd, typval_T *rettv)
 {
 #ifndef PY_CAN_RECURSE
     static int		recursive = 0;
@@ -639,8 +746,16 @@ DoPythonCommand(exarg_T *eap, const char
     if (Python_Init())
 	goto theend;
 
-    RangeStart = eap->line1;
-    RangeEnd = eap->line2;
+    if (rettv == NULL)
+    {
+	RangeStart = eap->line1;
+	RangeEnd = eap->line2;
+    }
+    else
+    {
+	RangeStart = (PyInt) curwin->w_cursor.lnum;
+	RangeEnd = RangeStart;
+    }
     Python_Release_Vim();	    /* leave vim */
 
 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
@@ -658,7 +773,23 @@ DoPythonCommand(exarg_T *eap, const char
 
     Python_RestoreThread();	    /* enter python */
 
-    PyRun_SimpleString((char *)(cmd));
+    if (rettv == NULL)
+	PyRun_SimpleString((char *)(cmd));
+    else
+    {
+	PyObject	*r;
+
+	r = PyRun_String((char *)(cmd), Py_eval_input, globals, globals);
+	if (r == NULL)
+	    EMSG(_("E858: Eval did not return a valid python object"));
+	else
+	{
+	    if (ConvertFromPyObject(r, rettv) == -1)
+		EMSG(_("E859: Failed to convert returned python object to vim value"));
+	    Py_DECREF(r);
+	}
+	PyErr_Clear();
+    }
 
     Python_SaveThread();	    /* leave python */
 
@@ -680,7 +811,7 @@ theend:
 #ifndef PY_CAN_RECURSE
     --recursive;
 #endif
-    return;	    /* keeps lint happy */
+    return;
 }
 
 /*
@@ -695,9 +826,9 @@ ex_python(exarg_T *eap)
     if (!eap->skip)
     {
 	if (script == NULL)
-	    DoPythonCommand(eap, (char *)eap->arg);
+	    DoPythonCommand(eap, (char *)eap->arg, NULL);
 	else
-	    DoPythonCommand(eap, (char *)script);
+	    DoPythonCommand(eap, (char *)script, NULL);
     }
     vim_free(script);
 }
@@ -743,7 +874,7 @@ ex_pyfile(exarg_T *eap)
     *p++ = '\0';
 
     /* Execute the file */
-    DoPythonCommand(eap, buffer);
+    DoPythonCommand(eap, buffer, NULL);
 }
 
 /******************************************************
@@ -765,14 +896,16 @@ OutputGetattr(PyObject *self, char *name
     static int
 OutputSetattr(PyObject *self, char *name, PyObject *val)
 {
-    if (val == NULL) {
+    if (val == NULL)
+    {
 	PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
 	return -1;
     }
 
     if (strcmp(name, "softspace") == 0)
     {
-	if (!PyInt_Check(val)) {
+	if (!PyInt_Check(val))
+	{
 	    PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
 	    return -1;
 	}
@@ -800,6 +933,9 @@ PythonIO_Init(void)
  * 3. Implementation of the Vim module for Python
  */
 
+static PyObject *ConvertToPyObject(typval_T *);
+static int ConvertFromPyObject(PyObject *, typval_T *);
+
 /* Window type - Implementation functions
  * --------------------------------------
  */
@@ -1441,6 +1577,172 @@ LineToString(const char *str)
     return result;
 }
 
+static void DictionaryDestructor(PyObject *);
+static PyObject *DictionaryGetattr(PyObject *, char*);
+
+static PyMappingMethods DictionaryAsMapping = {
+    (PyInquiry)		DictionaryLength,
+    (binaryfunc)	DictionaryItem,
+    (objobjargproc)	DictionaryAssItem,
+};
+
+static PyTypeObject DictionaryType = {
+    PyObject_HEAD_INIT(0)
+    0,
+    "vimdictionary",
+    sizeof(DictionaryObject),
+    0,
+
+    (destructor)  DictionaryDestructor,
+    (printfunc)   0,
+    (getattrfunc) DictionaryGetattr,
+    (setattrfunc) 0,
+    (cmpfunc)     0,
+    (reprfunc)    0,
+
+    0,			    /* as number */
+    0,			    /* as sequence */
+    &DictionaryAsMapping,   /* as mapping */
+
+    (hashfunc)    0,
+    (ternaryfunc) 0,
+    (reprfunc)    0,
+};
+
+    static void
+DictionaryDestructor(PyObject *self)
+{
+    DictionaryObject	*this = ((DictionaryObject *) (self));
+
+    pyll_remove(&this->ref, &lastdict);
+    dict_unref(this->dict);
+
+    Py_DECREF(self);
+}
+
+    static PyObject *
+DictionaryGetattr(PyObject *self, char *name)
+{
+    return Py_FindMethod(DictionaryMethods, self, name);
+}
+
+static void ListDestructor(PyObject *);
+static PyObject *ListGetattr(PyObject *, char *);
+
+static PySequenceMethods ListAsSeq = {
+    (PyInquiry)			ListLength,
+    (binaryfunc)		0,
+    (PyIntArgFunc)		0,
+    (PyIntArgFunc)		ListItem,
+    (PyIntIntArgFunc)		ListSlice,
+    (PyIntObjArgProc)		ListAssItem,
+    (PyIntIntObjArgProc)	ListAssSlice,
+    (objobjproc)		0,
+#if PY_MAJOR_VERSION >= 2
+    (binaryfunc)		ListConcatInPlace,
+    0,
+#endif
+};
+
+static PyTypeObject ListType = {
+    PyObject_HEAD_INIT(0)
+    0,
+    "vimlist",
+    sizeof(ListObject),
+    0,
+
+    (destructor)  ListDestructor,
+    (printfunc)   0,
+    (getattrfunc) ListGetattr,
+    (setattrfunc) 0,
+    (cmpfunc)     0,
+    (reprfunc)    0,
+
+    0,			    /* as number */
+    &ListAsSeq,		    /* as sequence */
+    0,			    /* as mapping */
+
+    (hashfunc)    0,
+    (ternaryfunc) 0,
+    (reprfunc)    0,
+};
+
+    static void
+ListDestructor(PyObject *self)
+{
+    ListObject	*this = ((ListObject *) (self));
+
+    pyll_remove(&this->ref, &lastlist);
+    list_unref(this->list);
+
+    Py_DECREF(self);
+}
+
+    static PyObject *
+ListGetattr(PyObject *self, char *name)
+{
+    return Py_FindMethod(ListMethods, self, name);
+}
+
+static void FunctionDestructor(PyObject *);
+static PyObject *FunctionGetattr(PyObject *, char *);
+
+static PyTypeObject FunctionType = {
+    PyObject_HEAD_INIT(0)
+    0,
+    "vimfunction",
+    sizeof(FunctionObject),
+    0,
+
+    (destructor)  FunctionDestructor,
+    (printfunc)   0,
+    (getattrfunc) FunctionGetattr,
+    (setattrfunc) 0,
+    (cmpfunc)     0,
+    (reprfunc)    0,
+
+    0,			    /* as number */
+    0,			    /* as sequence */
+    0,			    /* as mapping */
+
+    (hashfunc)    0,
+    (ternaryfunc) FunctionCall,
+    (reprfunc)    0,
+};
+
+    static void
+FunctionDestructor(PyObject *self)
+{
+    FunctionObject	*this = (FunctionObject *) (self);
+
+    func_unref(this->name);
+    PyMem_Del(this->name);
+
+    Py_DECREF(self);
+}
+
+    static PyObject *
+FunctionGetattr(PyObject *self, char *name)
+{
+    FunctionObject	*this = (FunctionObject *)(self);
+
+    if (strcmp(name, "name") == 0)
+	return PyString_FromString((char *)(this->name));
+    else
+	return Py_FindMethod(FunctionMethods, self, name);
+}
+
+    void
+do_pyeval (char_u *str, typval_T *rettv)
+{
+    DoPythonCommand(NULL, (char *) str, rettv);
+    switch(rettv->v_type)
+    {
+	case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break;
+	case VAR_LIST: ++rettv->vval.v_list->lv_refcount; break;
+	case VAR_FUNC: func_ref(rettv->vval.v_string);    break;
+    }
+}
 
 /* Don't generate a prototype for the next function, it generates an error on
  * newer Python versions. */
@@ -1453,6 +1755,12 @@ Py_GetProgramName(void)
 }
 #endif /* Python 1.4 */
 
+    void
+set_ref_in_python (int copyID)
+{
+    set_ref_in_py(copyID);
+}
+
     static void
 init_structs(void)
 {
--- a/src/if_python3.c
+++ b/src/if_python3.c
@@ -77,7 +77,7 @@ static void init_structs(void);
 
 #define PyInt Py_ssize_t
 #define PyString_Check(obj) PyUnicode_Check(obj)
-#define PyString_AsBytes(obj) PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, CODEC_ERROR_HANDLER);
+#define PyString_AsBytes(obj) PyUnicode_AsEncodedString(obj, (char *)ENC_OPT, CODEC_ERROR_HANDLER)
 #define PyString_FreeBytes(obj) Py_XDECREF(bytes)
 #define PyString_AsString(obj) PyBytes_AsString(obj)
 #define PyString_Size(obj) PyBytes_GET_SIZE(bytes)
@@ -109,6 +109,7 @@ static void init_structs(void);
 # undef PyArg_ParseTuple
 # define PyArg_ParseTuple py3_PyArg_ParseTuple
 # define PyMem_Free py3_PyMem_Free
+# define PyMem_Malloc py3_PyMem_Malloc
 # define PyDict_SetItemString py3_PyDict_SetItemString
 # define PyErr_BadArgument py3_PyErr_BadArgument
 # define PyErr_Clear py3_PyErr_Clear
@@ -128,14 +129,27 @@ static void init_structs(void);
 # define PyList_New py3_PyList_New
 # define PyList_SetItem py3_PyList_SetItem
 # define PyList_Size py3_PyList_Size
+# define PySequence_Check py3_PySequence_Check
+# define PySequence_Size py3_PySequence_Size
+# define PySequence_GetItem py3_PySequence_GetItem
+# define PyTuple_Size py3_PyTuple_Size
+# define PyTuple_GetItem py3_PyTuple_GetItem
 # define PySlice_GetIndicesEx py3_PySlice_GetIndicesEx
 # define PyImport_ImportModule py3_PyImport_ImportModule
+# define PyImport_AddModule py3_PyImport_AddModule
 # define PyObject_Init py3__PyObject_Init
 # define PyDict_New py3_PyDict_New
 # define PyDict_GetItemString py3_PyDict_GetItemString
+# define PyDict_Next py3_PyDict_Next
+# define PyMapping_Check py3_PyMapping_Check
+# define PyMapping_Items py3_PyMapping_Items
+# define PyIter_Next py3_PyIter_Next
+# define PyObject_GetIter py3_PyObject_GetIter
 # define PyModule_GetDict py3_PyModule_GetDict
 #undef PyRun_SimpleString
 # define PyRun_SimpleString py3_PyRun_SimpleString
+#undef PyRun_String
+# define PyRun_String py3_PyRun_String
 # define PySys_SetObject py3_PySys_SetObject
 # define PySys_SetArgv py3_PySys_SetArgv
 # define PyType_Type (*py3_PyType_Type)
@@ -147,6 +161,7 @@ static void init_structs(void);
 # define Py_Finalize py3_Py_Finalize
 # define Py_IsInitialized py3_Py_IsInitialized
 # define _Py_NoneStruct (*py3__Py_NoneStruct)
+# define _PyObject_NextNotImplemented (*py3__PyObject_NextNotImplemented)
 # define PyModule_AddObject py3_PyModule_AddObject
 # define PyImport_AppendInittab py3_PyImport_AppendInittab
 # define _PyUnicode_AsString py3__PyUnicode_AsString
@@ -154,8 +169,13 @@ static void init_structs(void);
 # define PyUnicode_AsEncodedString py3_PyUnicode_AsEncodedString
 # undef PyBytes_AsString
 # define PyBytes_AsString py3_PyBytes_AsString
+# undef PyBytes_FromString
+# define PyBytes_FromString py3_PyBytes_FromString
+# define PyFloat_FromDouble py3_PyFloat_FromDouble
+# define PyFloat_AsDouble py3_PyFloat_AsDouble
 # define PyObject_GenericGetAttr py3_PyObject_GenericGetAttr
 # define PySlice_Type (*py3_PySlice_Type)
+# define PyFloat_Type (*py3_PyFloat_Type)
 # define PyErr_NewException py3_PyErr_NewException
 # ifdef Py_DEBUG
 #  define _Py_NegativeRefcount py3__Py_NegativeRefcount
@@ -174,6 +194,9 @@ static void init_structs(void);
 # define PyUnicode_FromString py3_PyUnicode_FromString
 # undef PyUnicode_Decode
 # define PyUnicode_Decode py3_PyUnicode_Decode
+# define PyType_IsSubtype py3_PyType_IsSubtype
+# define PyCapsule_New py3_PyCapsule_New
+# define PyCapsule_GetPointer py3_PyCapsule_GetPointer
 
 # ifdef Py_DEBUG
 #  undef PyObject_NEW
@@ -194,22 +217,34 @@ static void (*py3_PyGILState_Release)(Py
 static int (*py3_PySys_SetObject)(char *, PyObject *);
 static PyObject* (*py3_PyList_Append)(PyObject *, PyObject *);
 static Py_ssize_t (*py3_PyList_Size)(PyObject *);
+static int (*py3_PySequence_Check)(PyObject *);
+static Py_ssize_t (*py3_PySequence_Size)(PyObject *);
+static PyObject* (*py3_PySequence_GetItem)(PyObject *, Py_ssize_t);
+static Py_ssize_t (*py3_PyTuple_Size)(PyObject *);
+static PyObject* (*py3_PyTuple_GetItem)(PyObject *, Py_ssize_t);
+static int (*py3_PyMapping_Check)(PyObject *);
+static PyObject* (*py3_PyMapping_Items)(PyObject *);
 static int (*py3_PySlice_GetIndicesEx)(PyObject *r, Py_ssize_t length,
 		     Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength);
 static PyObject* (*py3_PyErr_NoMemory)(void);
 static void (*py3_Py_Finalize)(void);
 static void (*py3_PyErr_SetString)(PyObject *, const char *);
 static int (*py3_PyRun_SimpleString)(char *);
+static PyObject* (*py3_PyRun_String)(char *, int, PyObject *, PyObject *);
 static PyObject* (*py3_PyList_GetItem)(PyObject *, Py_ssize_t);
 static PyObject* (*py3_PyImport_ImportModule)(const char *);
+static PyObject* (*py3_PyImport_AddModule)(const char *);
 static int (*py3_PyErr_BadArgument)(void);
 static PyTypeObject* py3_PyType_Type;
 static PyObject* (*py3_PyErr_Occurred)(void);
 static PyObject* (*py3_PyModule_GetDict)(PyObject *);
 static int (*py3_PyList_SetItem)(PyObject *, Py_ssize_t, PyObject *);
 static PyObject* (*py3_PyDict_GetItemString)(PyObject *, const char *);
+static int (*py3_PyDict_Next)(PyObject *, Py_ssize_t *, PyObject **, PyObject **);
 static PyObject* (*py3_PyLong_FromLong)(long);
 static PyObject* (*py3_PyDict_New)(void);
+static PyObject* (*py3_PyIter_Next)(PyObject *);
+static PyObject* (*py3_PyObject_GetIter)(PyObject *);
 static PyObject* (*py3_Py_BuildValue)(char *, ...);
 static int (*py3_PyType_Ready)(PyTypeObject *type);
 static int (*py3_PyDict_SetItemString)(PyObject *dp, char *key, PyObject *item);
@@ -224,21 +259,29 @@ static PyThreadState*(*py3_PyEval_SaveTh
 static int (*py3_PyArg_Parse)(PyObject *, char *, ...);
 static int (*py3_PyArg_ParseTuple)(PyObject *, char *, ...);
 static int (*py3_PyMem_Free)(void *);
+static void* (*py3_PyMem_Malloc)(size_t);
 static int (*py3_Py_IsInitialized)(void);
 static void (*py3_PyErr_Clear)(void);
 static PyObject*(*py3__PyObject_Init)(PyObject *, PyTypeObject *);
+static iternextfunc py3__PyObject_NextNotImplemented;
 static PyObject* py3__Py_NoneStruct;
 static int (*py3_PyModule_AddObject)(PyObject *m, const char *name, PyObject *o);
 static int (*py3_PyImport_AppendInittab)(const char *name, PyObject* (*initfunc)(void));
 static char* (*py3__PyUnicode_AsString)(PyObject *unicode);
 static PyObject* (*py3_PyUnicode_AsEncodedString)(PyObject *unicode, const char* encoding, const char* errors);
 static char* (*py3_PyBytes_AsString)(PyObject *bytes);
+static PyObject* (*py3_PyBytes_FromString)(char *str);
+static PyObject* (*py3_PyFloat_FromDouble)(double num);
+static double (*py3_PyFloat_AsDouble)(PyObject *);
 static PyObject* (*py3_PyObject_GenericGetAttr)(PyObject *obj, PyObject *name);
 static PyObject* (*py3_PyModule_Create2)(struct PyModuleDef* module, int module_api_version);
 static PyObject* (*py3_PyType_GenericAlloc)(PyTypeObject *type, Py_ssize_t nitems);
 static PyObject* (*py3_PyType_GenericNew)(PyTypeObject *type, PyObject *args, PyObject *kwds);
 static PyTypeObject* py3_PySlice_Type;
+static PyTypeObject* py3_PyFloat_Type;
 static PyObject* (*py3_PyErr_NewException)(char *name, PyObject *base, PyObject *dict);
+static PyObject* (*py3_PyCapsule_New)(void *, char *, PyCapsule_Destructor);
+static void* (*py3_PyCapsule_GetPointer)(PyObject *, char *);
 # ifdef Py_DEBUG
     static void (*py3__Py_NegativeRefcount)(const char *fname, int lineno, PyObject *op);
     static Py_ssize_t* py3__Py_RefTotal;
@@ -249,6 +292,7 @@ static PyObject* (*py3_PyErr_NewExceptio
     static void (*py3_PyObject_Free)(void*);
     static void* (*py3_PyObject_Malloc)(size_t);
 # endif
+static int (*py3_PyType_IsSubtype)(PyTypeObject *, PyTypeObject *);
 
 static HINSTANCE hinstPy3 = 0; /* Instance of python.dll */
 
@@ -280,25 +324,38 @@ static struct
     {"Py_Initialize", (PYTHON_PROC*)&py3_Py_Initialize},
     {"PyArg_ParseTuple", (PYTHON_PROC*)&py3_PyArg_ParseTuple},
     {"PyMem_Free", (PYTHON_PROC*)&py3_PyMem_Free},
+    {"PyMem_Malloc", (PYTHON_PROC*)&py3_PyMem_Malloc},
     {"PyList_New", (PYTHON_PROC*)&py3_PyList_New},
     {"PyGILState_Ensure", (PYTHON_PROC*)&py3_PyGILState_Ensure},
     {"PyGILState_Release", (PYTHON_PROC*)&py3_PyGILState_Release},
     {"PySys_SetObject", (PYTHON_PROC*)&py3_PySys_SetObject},
     {"PyList_Append", (PYTHON_PROC*)&py3_PyList_Append},
     {"PyList_Size", (PYTHON_PROC*)&py3_PyList_Size},
+    {"PySequence_Check", (PYTHON_PROC*)&py3_PySequence_Check},
+    {"PySequence_Size", (PYTHON_PROC*)&py3_PySequence_Size},
+    {"PySequence_GetItem", (PYTHON_PROC*)&py3_PySequence_GetItem},
+    {"PyTuple_Size", (PYTHON_PROC*)&py3_PyTuple_Size},
+    {"PyTuple_GetItem", (PYTHON_PROC*)&py3_PyTuple_GetItem},
     {"PySlice_GetIndicesEx", (PYTHON_PROC*)&py3_PySlice_GetIndicesEx},
     {"PyErr_NoMemory", (PYTHON_PROC*)&py3_PyErr_NoMemory},
     {"Py_Finalize", (PYTHON_PROC*)&py3_Py_Finalize},
     {"PyErr_SetString", (PYTHON_PROC*)&py3_PyErr_SetString},
     {"PyRun_SimpleString", (PYTHON_PROC*)&py3_PyRun_SimpleString},
+    {"PyRun_String", (PYTHON_PROC*)&py3_PyRun_String},
     {"PyList_GetItem", (PYTHON_PROC*)&py3_PyList_GetItem},
     {"PyImport_ImportModule", (PYTHON_PROC*)&py3_PyImport_ImportModule},
+    {"PyImport_AddModule", (PYTHON_PROC*)&py3_PyImport_AddModule},
     {"PyErr_BadArgument", (PYTHON_PROC*)&py3_PyErr_BadArgument},
     {"PyType_Type", (PYTHON_PROC*)&py3_PyType_Type},
     {"PyErr_Occurred", (PYTHON_PROC*)&py3_PyErr_Occurred},
     {"PyModule_GetDict", (PYTHON_PROC*)&py3_PyModule_GetDict},
     {"PyList_SetItem", (PYTHON_PROC*)&py3_PyList_SetItem},
     {"PyDict_GetItemString", (PYTHON_PROC*)&py3_PyDict_GetItemString},
+    {"PyDict_Next", (PYTHON_PROC*)&py3_PyDict_Next},
+    {"PyMapping_Check", (PYTHON_PROC*)&py3_PyMapping_Check},
+    {"PyMapping_Items", (PYTHON_PROC*)&py3_PyMapping_Items},
+    {"PyIter_Next", (PYTHON_PROC*)&py3_PyIter_Next},
+    {"PyObject_GetIter", (PYTHON_PROC*)&py3_PyObject_GetIter},
     {"PyLong_FromLong", (PYTHON_PROC*)&py3_PyLong_FromLong},
     {"PyDict_New", (PYTHON_PROC*)&py3_PyDict_New},
     {"Py_BuildValue", (PYTHON_PROC*)&py3_Py_BuildValue},
@@ -311,6 +368,7 @@ static struct
     {"PyEval_SaveThread", (PYTHON_PROC*)&py3_PyEval_SaveThread},
     {"PyArg_Parse", (PYTHON_PROC*)&py3_PyArg_Parse},
     {"Py_IsInitialized", (PYTHON_PROC*)&py3_Py_IsInitialized},
+    {"_PyObject_NextNotImplemented", (PYTHON_PROC*)&py3__PyObject_NextNotImplemented},
     {"_Py_NoneStruct", (PYTHON_PROC*)&py3__Py_NoneStruct},
     {"PyErr_Clear", (PYTHON_PROC*)&py3_PyErr_Clear},
     {"PyObject_Init", (PYTHON_PROC*)&py3__PyObject_Init},
@@ -318,11 +376,15 @@ static struct
     {"PyImport_AppendInittab", (PYTHON_PROC*)&py3_PyImport_AppendInittab},
     {"_PyUnicode_AsString", (PYTHON_PROC*)&py3__PyUnicode_AsString},
     {"PyBytes_AsString", (PYTHON_PROC*)&py3_PyBytes_AsString},
+    {"PyBytes_FromString", (PYTHON_PROC*)&py3_PyBytes_FromString},
+    {"PyFloat_FromDouble", (PYTHON_PROC*)&py3_PyFloat_FromDouble},
+    {"PyFloat_AsDouble", (PYTHON_PROC*)&py3_PyFloat_AsDouble},
     {"PyObject_GenericGetAttr", (PYTHON_PROC*)&py3_PyObject_GenericGetAttr},
     {"PyModule_Create2", (PYTHON_PROC*)&py3_PyModule_Create2},
     {"PyType_GenericAlloc", (PYTHON_PROC*)&py3_PyType_GenericAlloc},
     {"PyType_GenericNew", (PYTHON_PROC*)&py3_PyType_GenericNew},
     {"PySlice_Type", (PYTHON_PROC*)&py3_PySlice_Type},
+    {"PyFloat_Type", (PYTHON_PROC*)&py3_PyFloat_Type},
     {"PyErr_NewException", (PYTHON_PROC*)&py3_PyErr_NewException},
 # ifdef Py_DEBUG
     {"_Py_NegativeRefcount", (PYTHON_PROC*)&py3__Py_NegativeRefcount},
@@ -334,6 +396,9 @@ static struct
     {"PyObject_Malloc", (PYTHON_PROC*)&py3_PyObject_Malloc},
     {"PyObject_Free", (PYTHON_PROC*)&py3_PyObject_Free},
 # endif
+    {"PyType_IsSubtype", (PYTHON_PROC*)&py3_PyType_IsSubtype},
+    {"PyCapsule_New", (PYTHON_PROC*)&py3_PyCapsule_New},
+    {"PyCapsule_GetPointer", (PYTHON_PROC*)&py3_PyCapsule_GetPointer},
     {"", NULL},
 };
 
@@ -472,11 +537,41 @@ static PyObject *BufferDir(PyObject *, P
 
 static PyTypeObject RangeType;
 
+static int py3initialised = 0;
+
+#define PYINITIALISED py3initialised
+
+/* Add conversion from PyInt? */
+#define DICTKEY_GET(err) \
+    if (PyBytes_Check(keyObject)) \
+	key = (char_u *) PyBytes_AsString(keyObject); \
+    else if (PyUnicode_Check(keyObject)) \
+    { \
+	bytes = PyString_AsBytes(keyObject); \
+	if (bytes == NULL) \
+	    return err; \
+	key = (char_u *) PyBytes_AsString(bytes); \
+	if (key == NULL) \
+	    return err; \
+    } \
+    else \
+    { \
+	PyErr_SetString(PyExc_TypeError, _("only string keys are allowed")); \
+	return err; \
+    }
+#define DICTKEY_UNREF \
+    if (bytes != NULL) \
+	Py_XDECREF(bytes);
+
+#define DICTKEY_DECL PyObject *bytes = NULL;
+
 /*
  * Include the code shared with if_python.c
  */
 #include "if_py_both.h"
 
+#define PY3OBJ_DELETED(obj) (obj->ob_base.ob_refcnt<=0)
+
     static void
 call_PyObject_Free(void *p)
 {
@@ -506,6 +601,8 @@ call_PyType_GenericAlloc(PyTypeObject *t
 static Py_ssize_t RangeStart;
 static Py_ssize_t RangeEnd;
 
+static PyObject *globals;
+
 static int PythonIO_Init(void);
 static void PythonIO_Fini(void);
 PyMODINIT_FUNC Py3Init_vim(void);
@@ -514,8 +611,6 @@ PyMODINIT_FUNC Py3Init_vim(void);
  * 1. Python interpreter main program.
  */
 
-static int py3initialised = 0;
-
 static PyGILState_STATE pygilstate = PyGILState_UNLOCKED;
 
     void
@@ -593,6 +688,8 @@ Python3_Init(void)
 
 	PyImport_AppendInittab("vim", Py3Init_vim);
 
+	globals = PyModule_GetDict(PyImport_AddModule("__main__"));
+
 	/* Remove the element from sys.path that was added because of our
 	 * argv[0] value in Py3Init_vim().  Previously we used an empty
 	 * string, but dependinding on the OS we then get an empty entry or
@@ -629,7 +726,7 @@ fail:
  * External interface
  */
     static void
-DoPy3Command(exarg_T *eap, const char *cmd)
+DoPy3Command(exarg_T *eap, const char *cmd, typval_T *rettv)
 {
 #if defined(MACOS) && !defined(MACOS_X_UNIX)
     GrafPtr		oldPort;
@@ -649,8 +746,16 @@ DoPy3Command(exarg_T *eap, const char *c
     if (Python3_Init())
 	goto theend;
 
-    RangeStart = eap->line1;
-    RangeEnd = eap->line2;
+    if (rettv == NULL)
+    {
+	RangeStart = eap->line1;
+	RangeEnd = eap->line2;
+    }
+    else
+    {
+	RangeStart = (PyInt) curwin->w_cursor.lnum;
+	RangeEnd = RangeStart;
+    }
     Python_Release_Vim();	    /* leave vim */
 
 #if defined(HAVE_LOCALE_H) || defined(X_LOCALE)
@@ -674,7 +779,24 @@ DoPy3Command(exarg_T *eap, const char *c
 					(char *)ENC_OPT, CODEC_ERROR_HANDLER);
     cmdbytes = PyUnicode_AsEncodedString(cmdstr, "utf-8", CODEC_ERROR_HANDLER);
     Py_XDECREF(cmdstr);
-    PyRun_SimpleString(PyBytes_AsString(cmdbytes));
+    if (rettv == NULL)
+	PyRun_SimpleString(PyBytes_AsString(cmdbytes));
+    else
+    {
+	PyObject	*r;
+
+	r = PyRun_String(PyBytes_AsString(cmdbytes), Py_eval_input,
+			 globals, globals);
+	if (r == NULL)
+	    EMSG(_("E860: Eval did not return a valid python 3 object"));
+	else
+	{
+	    if (ConvertFromPyObject(r, rettv) == -1)
+		EMSG(_("E861: Failed to convert returned python 3 object to vim value"));
+	    Py_DECREF(r);
+	}
+	PyErr_Clear();
+    }
     Py_XDECREF(cmdbytes);
 
     PyGILState_Release(pygilstate);
@@ -709,9 +831,9 @@ ex_py3(exarg_T *eap)
     if (!eap->skip)
     {
 	if (script == NULL)
-	    DoPy3Command(eap, (char *)eap->arg);
+	    DoPy3Command(eap, (char *)eap->arg, NULL);
 	else
-	    DoPy3Command(eap, (char *)script);
+	    DoPy3Command(eap, (char *)script, NULL);
     }
     vim_free(script);
 }
@@ -772,7 +894,7 @@ ex_py3file(exarg_T *eap)
 
 
     /* Execute the file */
-    DoPy3Command(eap, buffer);
+    DoPy3Command(eap, buffer, NULL);
 }
 
 /******************************************************
@@ -802,14 +924,16 @@ OutputSetattro(PyObject *self, PyObject 
     if (PyUnicode_Check(nameobj))
 	name = _PyUnicode_AsString(nameobj);
 
-    if (val == NULL) {
+    if (val == NULL)
+    {
 	PyErr_SetString(PyExc_AttributeError, _("can't delete OutputObject attributes"));
 	return -1;
     }
 
     if (strcmp(name, "softspace") == 0)
     {
-	if (!PyLong_Check(val)) {
+	if (!PyLong_Check(val))
+	{
 	    PyErr_SetString(PyExc_TypeError, _("softspace must be an integer"));
 	    return -1;
 	}
@@ -1030,20 +1154,25 @@ BufferSlice(PyObject *self, Py_ssize_t l
     static PyObject *
 BufferSubscript(PyObject *self, PyObject* idx)
 {
-    if (PyLong_Check(idx)) {
+    if (PyLong_Check(idx))
+    {
 	long _idx = PyLong_AsLong(idx);
 	return BufferItem(self,_idx);
-    } else if (PySlice_Check(idx)) {
+    } else if (PySlice_Check(idx))
+    {
 	Py_ssize_t start, stop, step, slicelen;
 
 	if (PySlice_GetIndicesEx((PyObject *)idx,
 	      (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count+1,
 	      &start, &stop,
-	      &step, &slicelen) < 0) {
+	      &step, &slicelen) < 0)
+	{
 	    return NULL;
 	}
 	return BufferSlice(self, start, stop);
-    } else {
+    }
+    else
+    {
 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
 	return NULL;
     }
@@ -1052,24 +1181,29 @@ BufferSubscript(PyObject *self, PyObject
     static Py_ssize_t
 BufferAsSubscript(PyObject *self, PyObject* idx, PyObject* val)
 {
-    if (PyLong_Check(idx)) {
+    if (PyLong_Check(idx))
+    {
 	long n = PyLong_AsLong(idx);
 	return RBAsItem((BufferObject *)(self), n, val, 1,
 		    (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count,
 		    NULL);
-    } else if (PySlice_Check(idx)) {
+    } else if (PySlice_Check(idx))
+    {
 	Py_ssize_t start, stop, step, slicelen;
 
 	if (PySlice_GetIndicesEx((PyObject *)idx,
 	      (Py_ssize_t)((BufferObject *)(self))->buf->b_ml.ml_line_count+1,
 	      &start, &stop,
-	      &step, &slicelen) < 0) {
+	      &step, &slicelen) < 0)
+	{
 	    return -1;
 	}
 	return RBAsSlice((BufferObject *)(self), start, stop, val, 1,
 			  (PyInt)((BufferObject *)(self))->buf->b_ml.ml_line_count,
 			  NULL);
-    } else {
+    }
+    else
+    {
 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
 	return -1;
     }
@@ -1142,20 +1276,25 @@ RangeAsSlice(PyObject *self, Py_ssize_t 
     static PyObject *
 RangeSubscript(PyObject *self, PyObject* idx)
 {
-    if (PyLong_Check(idx)) {
+    if (PyLong_Check(idx))
+    {
 	long _idx = PyLong_AsLong(idx);
 	return RangeItem(self,_idx);
-    } else if (PySlice_Check(idx)) {
+    } else if (PySlice_Check(idx))
+    {
 	Py_ssize_t start, stop, step, slicelen;
 
 	if (PySlice_GetIndicesEx((PyObject *)idx,
 		((RangeObject *)(self))->end-((RangeObject *)(self))->start+1,
 		&start, &stop,
-		&step, &slicelen) < 0) {
+		&step, &slicelen) < 0)
+	{
 	    return NULL;
 	}
 	return RangeSlice(self, start, stop);
-    } else {
+    }
+    else
+    {
 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
 	return NULL;
     }
@@ -1164,20 +1303,25 @@ RangeSubscript(PyObject *self, PyObject*
     static Py_ssize_t
 RangeAsSubscript(PyObject *self, PyObject *idx, PyObject *val)
 {
-    if (PyLong_Check(idx)) {
+    if (PyLong_Check(idx))
+    {
 	long n = PyLong_AsLong(idx);
 	return RangeAsItem(self, n, val);
-    } else if (PySlice_Check(idx)) {
+    } else if (PySlice_Check(idx))
+    {
 	Py_ssize_t start, stop, step, slicelen;
 
 	if (PySlice_GetIndicesEx((PyObject *)idx,
 		((RangeObject *)(self))->end-((RangeObject *)(self))->start+1,
 		&start, &stop,
-		&step, &slicelen) < 0) {
+		&step, &slicelen) < 0)
+	{
 	    return -1;
 	}
 	return RangeAsSlice(self, start, stop, val);
-    } else {
+    }
+    else
+    {
 	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
 	return -1;
     }
@@ -1390,6 +1534,147 @@ CurrentSetattro(PyObject *self UNUSED, P
     }
 }
 
+/* Dictionary object - Definitions
+ */
+
+static PyInt DictionaryLength(PyObject *);
+
+static PyMappingMethods DictionaryAsMapping = {
+    /* mp_length	*/ (lenfunc) DictionaryLength,
+    /* mp_subscript     */ (binaryfunc) DictionaryItem,
+    /* mp_ass_subscript */ (objobjargproc) DictionaryAssItem,
+};
+
+static PyTypeObject DictionaryType;
+
+    static void
+DictionaryDestructor(PyObject *self)
+{
+    DictionaryObject *this = (DictionaryObject *)(self);
+
+    pyll_remove(&this->ref, &lastdict);
+    dict_unref(this->dict);
+
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+/* List object - Definitions
+ */
+
+static PyInt ListLength(PyObject *);
+static PyObject *ListItem(PyObject *, Py_ssize_t);
+
+static PySequenceMethods ListAsSeq = {
+    (lenfunc)		ListLength,	 /* sq_length,	  len(x)   */
+    (binaryfunc)	0,		 /* RangeConcat, sq_concat,  x+y   */
+    (ssizeargfunc)	0,		 /* RangeRepeat, sq_repeat,  x*n   */
+    (ssizeargfunc)	ListItem,	 /* sq_item,	  x[i]	   */
+    (void *)		0,		 /* was_sq_slice,     x[i:j]   */
+    (ssizeobjargproc)	ListAssItem,	 /* sq_as_item,  x[i]=v   */
+    (void *)		0,		 /* was_sq_ass_slice, x[i:j]=v */
+    0,					 /* sq_contains */
+    (binaryfunc)	ListConcatInPlace,/* sq_inplace_concat */
+    0,					 /* sq_inplace_repeat */
+};
+
+static PyObject *ListSubscript(PyObject *, PyObject *);
+static Py_ssize_t ListAsSubscript(PyObject *, PyObject *, PyObject *);
+
+static PyMappingMethods ListAsMapping = {
+    /* mp_length	*/ (lenfunc) ListLength,
+    /* mp_subscript     */ (binaryfunc) ListSubscript,
+    /* mp_ass_subscript */ (objobjargproc) ListAsSubscript,
+};
+
+static PyTypeObject ListType;
+
+    static PyObject *
+ListSubscript(PyObject *self, PyObject* idxObject)
+{
+    if (PyLong_Check(idxObject))
+    {
+	long idx = PyLong_AsLong(idxObject);
+	return ListItem(self, idx);
+    }
+    else if (PySlice_Check(idxObject))
+    {
+	Py_ssize_t start, stop, step, slicelen;
+
+	if (PySlice_GetIndicesEx(idxObject, ListLength(self), &start, &stop,
+				 &step, &slicelen) < 0)
+	    return NULL;
+	return ListSlice(self, start, stop);
+    }
+    else
+    {
+	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+	return NULL;
+    }
+}
+
+    static Py_ssize_t
+ListAsSubscript(PyObject *self, PyObject *idxObject, PyObject *obj)
+{
+    if (PyLong_Check(idxObject))
+    {
+	long idx = PyLong_AsLong(idxObject);
+	return ListAssItem(self, idx, obj);
+    }
+    else if (PySlice_Check(idxObject))
+    {
+	Py_ssize_t start, stop, step, slicelen;
+
+	if (PySlice_GetIndicesEx(idxObject, ListLength(self), &start, &stop,
+				 &step, &slicelen) < 0)
+	    return -1;
+	return ListAssSlice(self, start, stop, obj);
+    }
+    else
+    {
+	PyErr_SetString(PyExc_IndexError, "Index must be int or slice");
+	return -1;
+    }
+}
+
+    static void
+ListDestructor(PyObject *self)
+{
+    ListObject *this = (ListObject *)(self);
+
+    pyll_remove(&this->ref, &lastlist);
+    list_unref(this->list);
+
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+/* Function object - Definitions
+ */
+
+    static void
+FunctionDestructor(PyObject *self)
+{
+    FunctionObject	*this = (FunctionObject *) (self);
+
+    func_unref(this->name);
+    PyMem_Del(this->name);
+
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+    static PyObject *
+FunctionGetattro(PyObject *self, PyObject *nameobj)
+{
+    FunctionObject	*this = (FunctionObject *)(self);
+    char	*name = "";
+    if (PyUnicode_Check(nameobj))
+	name = _PyUnicode_AsString(nameobj);
+
+    if (strcmp(name, "name") == 0)
+	return PyUnicode_FromString((char *)(this->name));
+
+    return PyObject_GenericGetAttr(self, nameobj);
+}
+
 /* External interface
  */
 
@@ -1449,6 +1734,9 @@ PyMODINIT_FUNC Py3Init_vim(void)
     PyType_Ready(&BufListType);
     PyType_Ready(&WinListType);
     PyType_Ready(&CurrentType);
+    PyType_Ready(&DictionaryType);
+    PyType_Ready(&ListType);
+    PyType_Ready(&FunctionType);
 
     /* Set sys.argv[] to avoid a crash in warn(). */
     PySys_SetArgv(1, argv);
@@ -1517,6 +1805,24 @@ LineToString(const char *str)
     return result;
 }
 
+    void
+do_py3eval (char_u *str, typval_T *rettv)
+{
+    DoPy3Command(NULL, (char *) str, rettv);
+    switch(rettv->v_type)
+    {
+	case VAR_DICT: ++rettv->vval.v_dict->dv_refcount; break;
+	case VAR_LIST: ++rettv->vval.v_list->lv_refcount; break;
+	case VAR_FUNC: func_ref(rettv->vval.v_string);    break;
+    }
+}
+
+    void
+set_ref_in_python3 (int copyID)
+{
+    set_ref_in_py(copyID);
+}
+
     static void
 init_structs(void)
 {
@@ -1598,6 +1904,35 @@ init_structs(void)
     CurrentType.tp_flags = Py_TPFLAGS_DEFAULT;
     CurrentType.tp_doc = "vim current object";
 
+    vim_memset(&DictionaryType, 0, sizeof(DictionaryType));
+    DictionaryType.tp_name = "vim.dictionary";
+    DictionaryType.tp_basicsize = sizeof(DictionaryObject);
+    DictionaryType.tp_dealloc = DictionaryDestructor;
+    DictionaryType.tp_as_mapping = &DictionaryAsMapping;
+    DictionaryType.tp_flags = Py_TPFLAGS_DEFAULT;
+    DictionaryType.tp_doc = "dictionary pushing modifications to vim structure";
+    DictionaryType.tp_methods = DictionaryMethods;
+
+    vim_memset(&ListType, 0, sizeof(ListType));
+    ListType.tp_name = "vim.list";
+    ListType.tp_dealloc = ListDestructor;
+    ListType.tp_basicsize = sizeof(ListObject);
+    ListType.tp_as_sequence = &ListAsSeq;
+    ListType.tp_as_mapping = &ListAsMapping;
+    ListType.tp_flags = Py_TPFLAGS_DEFAULT;
+    ListType.tp_doc = "list pushing modifications to vim structure";
+    ListType.tp_methods = ListMethods;
+
+    vim_memset(&FunctionType, 0, sizeof(FunctionType));
+    FunctionType.tp_name = "vim.list";
+    FunctionType.tp_basicsize = sizeof(FunctionObject);
+    FunctionType.tp_getattro = FunctionGetattro;
+    FunctionType.tp_dealloc = FunctionDestructor;
+    FunctionType.tp_call = FunctionCall;
+    FunctionType.tp_flags = Py_TPFLAGS_DEFAULT;
+    FunctionType.tp_doc = "object that calls vim function";
+    FunctionType.tp_methods = FunctionMethods;
+
     vim_memset(&vimmodule, 0, sizeof(vimmodule));
     vimmodule.m_name = "vim";
     vimmodule.m_doc = vim_module_doc;
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -46,12 +46,21 @@ char_u *get_user_var_name __ARGS((expand
 list_T *list_alloc __ARGS((void));
 void list_unref __ARGS((list_T *l));
 void list_free __ARGS((list_T *l, int recurse));
+listitem_T *listitem_alloc __ARGS((void));
+void listitem_remove __ARGS((list_T *l, listitem_T *item));
 dictitem_T *dict_lookup __ARGS((hashitem_T *hi));
+listitem_T *list_find __ARGS((list_T *l, long n));
 char_u *list_find_str __ARGS((list_T *l, long idx));
+void list_append __ARGS((list_T *l, listitem_T *item));
 int list_append_tv __ARGS((list_T *l, typval_T *tv));
 int list_append_dict __ARGS((list_T *list, dict_T *dict));
 int list_append_string __ARGS((list_T *l, char_u *str, int len));
+int list_insert_tv __ARGS((list_T *l, typval_T *tv, listitem_T *item));
+void list_remove __ARGS((list_T *l, listitem_T *item, listitem_T *item2));
 int garbage_collect __ARGS((void));
+void set_ref_in_ht __ARGS((hashtab_T *ht, int copyID));
+void set_ref_in_list __ARGS((list_T *l, int copyID));
+void set_ref_in_item __ARGS((typval_T *tv, int copyID));
 dict_T *dict_alloc __ARGS((void));
 void dict_unref __ARGS((dict_T *d));
 dictitem_T *dictitem_alloc __ARGS((char_u *key));
@@ -64,6 +73,7 @@ char_u *get_dict_string __ARGS((dict_T *
 long get_dict_number __ARGS((dict_T *d, char_u *key));
 char_u *get_function_name __ARGS((expand_T *xp, int idx));
 char_u *get_expr_name __ARGS((expand_T *xp, int idx));
+int func_call __ARGS((char_u *name, typval_T *args, dict_T *selfdict, typval_T *rettv));
 long do_searchpair __ARGS((char_u *spat, char_u *mpat, char_u *epat, int dir, char_u *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, long time_limit));
 void set_vim_var_nr __ARGS((int idx, long val));
 long get_vim_var_nr __ARGS((int idx));
@@ -94,6 +104,8 @@ void free_all_functions __ARGS((void));
 void func_dump_profile __ARGS((FILE *fd));
 char_u *get_user_func_name __ARGS((expand_T *xp, int idx));
 void ex_delfunction __ARGS((exarg_T *eap));
+void func_unref __ARGS((char_u *name));
+void func_ref __ARGS((char_u *name));
 void ex_return __ARGS((exarg_T *eap));
 int do_return __ARGS((exarg_T *eap, int reanimate, int is_cmd, void *rettv));
 void discard_pending_return __ARGS((void *rettv));
--- a/src/proto/if_python.pro
+++ b/src/proto/if_python.pro
@@ -6,4 +6,6 @@ void ex_python __ARGS((exarg_T *eap));
 void ex_pyfile __ARGS((exarg_T *eap));
 void python_buffer_free __ARGS((buf_T *buf));
 void python_window_free __ARGS((win_T *win));
+void do_pyeval __ARGS((char_u *str, typval_T *rettv));
+void set_ref_in_python __ARGS((int copyID));
 /* vim: set ft=c : */
--- a/src/proto/if_python3.pro
+++ b/src/proto/if_python3.pro
@@ -6,4 +6,6 @@ void ex_py3 __ARGS((exarg_T *eap));
 void ex_py3file __ARGS((exarg_T *eap));
 void python3_buffer_free __ARGS((buf_T *buf));
 void python3_window_free __ARGS((win_T *win));
+void do_py3eval __ARGS((char_u *str, typval_T *rettv));
+void set_ref_in_python3 __ARGS((int copyID));
 /* vim: set ft=c : */
--- a/src/testdir/Make_amiga.mak
+++ b/src/testdir/Make_amiga.mak
@@ -14,6 +14,7 @@ VIMPROG = /vim
 # test27	can't edit file with "*"
 # test52	only for Win32
 # test85	no Lua interface
+# test86, 87	no Python interface
 
 SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
 		test7.out test8.out test9.out \
--- a/src/testdir/Make_dos.mak
+++ b/src/testdir/Make_dos.mak
@@ -30,7 +30,7 @@ SCRIPTS =	test3.out test4.out test5.out 
 		test68.out test69.out test71.out test72.out test73.out \
 		test74.out test75.out test76.out test77.out test78.out \
 		test79.out test80.out test81.out test82.out test83.out \
-		test84.out test85.out
+		test84.out test85.out test86.out test87.out
 
 SCRIPTS32 =	test50.out test70.out
 
--- a/src/testdir/Make_ming.mak
+++ b/src/testdir/Make_ming.mak
@@ -50,7 +50,7 @@ SCRIPTS =	test3.out test4.out test5.out 
 		test68.out test69.out test71.out test72.out test73.out \
 		test74.out test75.out test76.out test77.out test78.out \
 		test79.out test80.out test81.out test82.out test83.out \
-		test84.out test85.out
+		test84.out test85.out test86.out test87.out
 
 SCRIPTS32 =	test50.out test70.out
 
--- a/src/testdir/Make_os2.mak
+++ b/src/testdir/Make_os2.mak
@@ -14,6 +14,7 @@ VIMPROG = ../vim.exe
 # test27	can't edit file with "*" in file name
 # test52	only for Win32
 # test85	no Lua interface
+# test86, 87	no Python interface
 
 SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
 		test7.out test8.out test9.out \
--- a/src/testdir/Makefile
+++ b/src/testdir/Makefile
@@ -27,7 +27,7 @@ SCRIPTS = test1.out test2.out test3.out 
 		test69.out test70.out test71.out test72.out test73.out \
 		test74.out test75.out test76.out test77.out test78.out \
 		test79.out test80.out test81.out test82.out test83.out \
-		test84.out test85.out
+		test84.out test85.out test86.out test87.out
 
 SCRIPTS_GUI = test16.out
 
new file mode 100644
--- /dev/null
+++ b/src/testdir/test86.in
@@ -0,0 +1,211 @@
+Tests for various python features.     vim: set ft=vim :
+
+STARTTEST
+:so small.vim
+:if !has('python') | e! test.ok | wq! test.out | endif
+:py import vim
+:fun Test()
+:let l = []
+:py l=vim.bindeval('l')
+:py f=vim.bindeval('function("strlen")')
+:" Extending List directly with different types
+:py l.extend([1, "as'd", [1, 2, f, {'a': 1}]])
+:$put =string(l)
+:$put =string(l[-1])
+:try
+:  $put =string(l[-4])
+:catch
+:  $put =v:exception[:13]
+:endtry
+:" List assignment
+:py l[0]=0
+:$put =string(l)
+:py l[-2]=f
+:$put =string(l)
+:"
+:" Extending Dictionary directly with different types
+:let d = {}
+:py d=vim.bindeval('d')
+:py d['1']='asd'
+:py d['b']=[1, 2, f]
+:py d['-1']={'a': 1}
+:let dkeys = []
+:py dk=vim.bindeval('dkeys')
+:py dkeys=d.keys()
+:py dkeys.sort()
+:py dk.extend(dkeys)
+:$put =string(dkeys)
+:for [key, val] in sort(items(d))
+:  $put =string(key) . ' : ' . string(val)
+:  unlet key val
+:endfor
+:"
+:" removing items with del
+:py del l[2]
+:$put =string(l)
+:let l = range(8)
+:py l=vim.bindeval('l')
+:try
+:   py del l[:3]
+:   py del l[1:]
+:catch
+:   $put =v:exception
+:endtry
+:$put =string(l)
+:"
+:py del d['-1']
+:$put =string(d)
+:"
+:" removing items out of range: silently skip items that don't exist
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:" The following two ranges delete nothing as they match empty list:
+:py del l[2:1]
+:$put =string(l)
+:py del l[2:2]
+:$put =string(l)
+:py del l[2:3]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[2:4]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[2:5]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[2:6]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:" The following two ranges delete nothing as they match empty list:
+:py del l[-1:2]
+:$put =string(l)
+:py del l[-2:2]
+:$put =string(l)
+:py del l[-3:2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[-4:2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[-5:2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py del l[-6:2]
+:$put =string(l)
+:"
+:" Slice assignment to a list
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[0:0]=['a']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[1:2]=['b']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[2:4]=['c']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[4:4]=['d']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[-1:2]=['e']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[-10:2]=['f']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:py l[2:-10]=['g']
+:$put =string(l)
+:let l = []
+:py l=vim.bindeval('l')
+:py l[0:0]=['h']
+:$put =string(l)
+:"
+:" Locked variables
+:let l = [0, 1, 2, 3]
+:py l=vim.bindeval('l')
+:lockvar! l
+:py l[2]='i'
+:$put =string(l)
+:unlockvar! l
+:"
+:" Function calls
+:function New(...)
+:return ['NewStart']+a:000+['NewEnd']
+:endfunction
+:function DictNew(...) dict
+:return ['DictNewStart']+a:000+['DictNewEnd', self]
+:endfunction
+:let l=[function('New'), function('DictNew')]
+:py l=vim.bindeval('l')
+:py l.extend(list(l[0](1, 2, 3)))
+:$put =string(l)
+:py l.extend(list(l[1](1, 2, 3, self={'a': 'b'})))
+:$put =string(l)
+:py l.extend([l[0].name])
+:$put =string(l)
+:try
+:   py l[1](1, 2, 3)
+:catch
+:   $put =v:exception[:16]
+:endtry
+:delfunction New
+:try
+:   py l[0](1, 2, 3)
+:catch
+:   $put =v:exception[:16]
+:endtry
+:if has('float')
+:   let l=[0.0]
+:   py l=vim.bindeval('l')
+:   py l.extend([0.0])
+:   $put =string(l)
+:else
+:   $put ='[0.0, 0.0]'
+:endif
+:"
+:" pyeval()
+:let l=pyeval('range(3)')
+:$put =string(l)
+:let d=pyeval('{"a": "b", "c": 1, "d": ["e"]}')
+:$put =sort(items(d))
+:try
+:   let undef=pyeval('undefined_name')
+:catch
+:   $put =v:exception[:13]
+:endtry
+:try
+:   let vim=pyeval('vim')
+:catch
+:   $put =v:exception[:13]
+:endtry
+:if has('float')
+:   let f=pyeval('0.0')
+:   $put =string(f)
+:else
+:   $put ='0.0'
+:endif
+:endfun
+:"
+:call Test()
+:"
+:delfunc Test
+:call garbagecollect(1)
+:"
+:/^start:/,$wq! test.out
+ENDTEST
+
+start:
new file mode 100644
--- /dev/null
+++ b/src/testdir/test86.ok
@@ -0,0 +1,47 @@
+start:
+[1, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
+[1, 2, function('strlen'), {'a': 1}]
+Vim(put):E684:
+[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
+[0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
+['-1', '1', 'b']
+'-1' : {'a': 1}
+'1' : 'asd'
+'b' : [1, 2, function('strlen')]
+[0, function('strlen')]
+[3]
+{'1': 'asd', 'b': [1, 2, function('strlen')]}
+[0, 1, 2, 3]
+[0, 1, 2, 3]
+[0, 1, 3]
+[0, 1]
+[0, 1]
+[0, 1]
+[0, 1, 2, 3]
+[0, 1, 2, 3]
+[0, 2, 3]
+[2, 3]
+[2, 3]
+[2, 3]
+['a', 0, 1, 2, 3]
+[0, 'b', 2, 3]
+[0, 1, 'c']
+[0, 1, 2, 3, 'd']
+[0, 1, 2, 'e', 3]
+['f', 2, 3]
+[0, 1, 'g', 2, 3]
+['h']
+[0, 1, 2, 3]
+[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd']
+[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}]
+[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}, 'New']
+Vim(python):E725:
+Vim(python):E117:
+[0.0, 0.0]
+[0, 1, 2]
+['a', 'b']
+['c', 1]
+['d', ['e']]
+Vim(let):E858:
+Vim(let):E859:
+0.0
new file mode 100644
--- /dev/null
+++ b/src/testdir/test87.in
@@ -0,0 +1,211 @@
+Tests for various python features.     vim: set ft=vim :
+
+STARTTEST
+:so small.vim
+:if !has('python3') | e! test.ok | wq! test.out | endif
+:py3 import vim
+:fun Test()
+:let l = []
+:py3 l=vim.bindeval('l')
+:py3 f=vim.bindeval('function("strlen")')
+:" Extending List directly with different types
+:py3 l+=[1, "as'd", [1, 2, f, {'a': 1}]]
+:$put =string(l)
+:$put =string(l[-1])
+:try
+:  $put =string(l[-4])
+:catch
+:  $put =v:exception[:13]
+:endtry
+:" List assignment
+:py3 l[0]=0
+:$put =string(l)
+:py3 l[-2]=f
+:$put =string(l)
+:"
+:" Extending Dictionary directly with different types
+:let d = {}
+:py3 d=vim.bindeval('d')
+:py3 d['1']='asd'
+:py3 d['b']=[1, 2, f]
+:py3 d['-1']={'a': 1}
+:let dkeys = []
+:py3 dk=vim.bindeval('dkeys')
+:py3 dkeys=d.keys()
+:py3 dkeys.sort()
+:py3 dk+=dkeys
+:$put =string(dkeys)
+:for [key, val] in sort(items(d))
+:  $put =string(key) . ' : ' . string(val)
+:  unlet key val
+:endfor
+:"
+:" removing items with del
+:py3 del l[2]
+:$put =string(l)
+:let l = range(8)
+:py3 l=vim.bindeval('l')
+:try
+:   py3 del l[:3]
+:   py3 del l[1:]
+:catch
+:   $put =v:exception
+:endtry
+:$put =string(l)
+:"
+:py3 del d['-1']
+:$put =string(d)
+:"
+:" removing items out of range: silently skip items that don't exist
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:" The following two ranges delete nothing as they match empty list:
+:py3 del l[2:1]
+:$put =string(l)
+:py3 del l[2:2]
+:$put =string(l)
+:py3 del l[2:3]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[2:4]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[2:5]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[2:6]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:" The following two ranges delete nothing as they match empty list:
+:py3 del l[-1:2]
+:$put =string(l)
+:py3 del l[-2:2]
+:$put =string(l)
+:py3 del l[-3:2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[-4:2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[-5:2]
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 del l[-6:2]
+:$put =string(l)
+:"
+:" Slice assignment to a list
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[0:0]=['a']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[1:2]=['b']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[2:4]=['c']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[4:4]=['d']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[-1:2]=['e']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[-10:2]=['f']
+:$put =string(l)
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:py3 l[2:-10]=['g']
+:$put =string(l)
+:let l = []
+:py3 l=vim.bindeval('l')
+:py3 l[0:0]=['h']
+:$put =string(l)
+:"
+:" Locked variables
+:let l = [0, 1, 2, 3]
+:py3 l=vim.bindeval('l')
+:lockvar! l
+:py3 l[2]='i'
+:$put =string(l)
+:unlockvar! l
+:"
+:" Function calls
+:function New(...)
+:return ['NewStart']+a:000+['NewEnd']
+:endfunction
+:function DictNew(...) dict
+:return ['DictNewStart']+a:000+['DictNewEnd', self]
+:endfunction
+:let l=[function('New'), function('DictNew')]
+:py3 l=vim.bindeval('l')
+:py3 l.extend(list(l[0](1, 2, 3)))
+:$put =string(l)
+:py3 l.extend(list(l[1](1, 2, 3, self={'a': 'b'})))
+:$put =string(l)
+:py3 l+=[l[0].name]
+:$put =string(l)
+:try
+:   py3 l[1](1, 2, 3)
+:catch
+:   $put =v:exception[:13]
+:endtry
+:delfunction New
+:try
+:   py3 l[0](1, 2, 3)
+:catch
+:   $put =v:exception[:13]
+:endtry
+:if has('float')
+:   let l=[0.0]
+:   py3 l=vim.bindeval('l')
+:   py3 l.extend([0.0])
+:   $put =string(l)
+:else
+:   $put ='[0.0, 0.0]'
+:endif
+:"
+:" py3eval()
+:let l=py3eval('[0, 1, 2]')
+:$put =string(l)
+:let d=py3eval('{"a": "b", "c": 1, "d": ["e"]}')
+:$put =sort(items(d))
+:try
+:   let undef=py3eval('undefined_name')
+:catch
+:   $put =v:exception[:13]
+:endtry
+:try
+:   let vim=py3eval('vim')
+:catch
+:   $put =v:exception[:13]
+:endtry
+:if has('float')
+:   let f=py3eval('0.0')
+:   $put =string(f)
+:else
+:   $put ='0.0'
+:endif
+:endfun
+:"
+:call Test()
+:"
+:delfunc Test
+:call garbagecollect(1)
+:"
+:/^start:/,$wq! test.out
+ENDTEST
+
+start:
new file mode 100644
--- /dev/null
+++ b/src/testdir/test87.ok
@@ -0,0 +1,47 @@
+start:
+[1, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
+[1, 2, function('strlen'), {'a': 1}]
+Vim(put):E684:
+[0, 'as''d', [1, 2, function('strlen'), {'a': 1}]]
+[0, function('strlen'), [1, 2, function('strlen'), {'a': 1}]]
+['-1', '1', 'b']
+'-1' : {'a': 1}
+'1' : 'asd'
+'b' : [1, 2, function('strlen')]
+[0, function('strlen')]
+[3]
+{'1': 'asd', 'b': [1, 2, function('strlen')]}
+[0, 1, 2, 3]
+[0, 1, 2, 3]
+[0, 1, 3]
+[0, 1]
+[0, 1]
+[0, 1]
+[0, 1, 2, 3]
+[0, 1, 2, 3]
+[0, 2, 3]
+[2, 3]
+[2, 3]
+[2, 3]
+['a', 0, 1, 2, 3]
+[0, 'b', 2, 3]
+[0, 1, 'c']
+[0, 1, 2, 3, 'd']
+[0, 1, 2, 'e', 3]
+['f', 2, 3]
+[0, 1, 'g', 2, 3]
+['h']
+[0, 1, 2, 3]
+[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd']
+[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}]
+[function('New'), function('DictNew'), 'NewStart', 1, 2, 3, 'NewEnd', 'DictNewStart', 1, 2, 3, 'DictNewEnd', {'a': 'b'}, 'New']
+Vim(py3):E725:
+Vim(py3):E117:
+[0.0, 0.0]
+[0, 1, 2]
+['a', 'b']
+['c', 1]
+['d', ['e']]
+Vim(let):E860:
+Vim(let):E861:
+0.0
--- a/src/version.c
+++ b/src/version.c
@@ -715,6 +715,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    569,
+/**/
     568,
 /**/
     567,