Skip to content

Commit 3416cee

Browse files
yegappanchrisbra
authored andcommitted
patch 9.1.1577: Vim9: no generic support yet
Problem: Vim9: no generic support yet Solution: Add support for generic functions, funcrefs and object/class methods (Yegappan Lakshmanan). closes: #17313 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent b486ed8 commit 3416cee

35 files changed

+5906
-162
lines changed

Filelist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ SRC_ALL = \
177177
src/vim9compile.c \
178178
src/vim9execute.c \
179179
src/vim9expr.c \
180+
src/vim9generics.c \
180181
src/vim9instr.c \
181182
src/vim9script.c \
182183
src/vim9type.c \
@@ -362,6 +363,7 @@ SRC_ALL = \
362363
src/proto/vim9compile.pro \
363364
src/proto/vim9execute.pro \
364365
src/proto/vim9expr.pro \
366+
src/proto/vim9generics.pro \
365367
src/proto/vim9instr.pro \
366368
src/proto/vim9script.pro \
367369
src/proto/vim9type.pro \

runtime/doc/tags

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4615,6 +4615,9 @@ E1425 vim9class.txt /*E1425*
46154615
E1426 vim9class.txt /*E1426*
46164616
E1429 vim9class.txt /*E1429*
46174617
E143 autocmd.txt /*E143*
4618+
E1432 vim9.txt /*E1432*
4619+
E1433 vim9.txt /*E1433*
4620+
E1434 vim9.txt /*E1434*
46184621
E144 various.txt /*E144*
46194622
E145 starting.txt /*E145*
46204623
E146 change.txt /*E146*
@@ -4674,7 +4677,17 @@ E1548 wayland.txt /*E1548*
46744677
E1549 options.txt /*E1549*
46754678
E155 sign.txt /*E155*
46764679
E1550 options.txt /*E1550*
4680+
E1552 vim9.txt /*E1552*
4681+
E1553 vim9.txt /*E1553*
4682+
E1554 vim9.txt /*E1554*
4683+
E1555 vim9.txt /*E1555*
4684+
E1556 vim9.txt /*E1556*
4685+
E1557 vim9.txt /*E1557*
4686+
E1558 vim9.txt /*E1558*
4687+
E1559 vim9.txt /*E1559*
46774688
E156 sign.txt /*E156*
4689+
E1560 vim9.txt /*E1560*
4690+
E1561 vim9.txt /*E1561*
46784691
E157 sign.txt /*E157*
46794692
E158 sign.txt /*E158*
46804693
E159 sign.txt /*E159*
@@ -7963,6 +7976,9 @@ gdb debug.txt /*gdb*
79637976
gdb-version terminal.txt /*gdb-version*
79647977
ge motion.txt /*ge*
79657978
gender-neutral helphelp.txt /*gender-neutral*
7979+
generic-function-call vim9.txt /*generic-function-call*
7980+
generic-function-declaration vim9.txt /*generic-function-declaration*
7981+
generic-functions vim9.txt /*generic-functions*
79667982
get() builtin.txt /*get()*
79677983
get()-blob builtin.txt /*get()-blob*
79687984
get()-dict builtin.txt /*get()-dict*
@@ -11023,6 +11039,7 @@ type-casting vim9.txt /*type-casting*
1102311039
type-checking vim9.txt /*type-checking*
1102411040
type-inference vim9.txt /*type-inference*
1102511041
type-mistakes tips.txt /*type-mistakes*
11042+
type-variable-naming vim9.txt /*type-variable-naming*
1102611043
typealias vim9class.txt /*typealias*
1102711044
typename() builtin.txt /*typename()*
1102811045
typescript.vim syntax.txt /*typescript.vim*

runtime/doc/todo.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*todo.txt* For Vim version 9.1. Last change: 2025 Jun 12
1+
*todo.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -115,7 +115,6 @@ Further Vim9 improvements:
115115
- For chaining, allow using the class name as type for function return
116116
value.
117117
- Implement "specifies" interface
118-
- Implement generics
119118
- Add "assignable" (class or child)?
120119
- More efficient way for interface member index than iterating over list?
121120
- a variant of type() that returns a different type for each class?

runtime/doc/version9.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41551,6 +41551,8 @@ Add support for internal builtin functions with vim9 objects, see
4155141551

4155241552
Enum support for Vim9 script |:enum|
4155341553

41554+
Generic function support for Vim9 script |generic-functions|
41555+
4155441556
Support for protected _new() method
4155541557

4155641558
Support for compiling all the methods in a Vim9 class using |:defcompile|.

runtime/doc/vim9.txt

Lines changed: 147 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*vim9.txt* For Vim version 9.1. Last change: 2025 Apr 27
1+
*vim9.txt* For Vim version 9.1. Last change: 2025 Jul 21
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -15,10 +15,11 @@ features in Vim9 script.
1515
2. Differences |vim9-differences|
1616
3. New style functions |fast-functions|
1717
4. Types |vim9-types|
18-
5. Namespace, Import and Export |vim9script|
19-
6. Classes and interfaces |vim9-classes|
18+
5. Generic functions |generic-functions|
19+
6. Namespace, Import and Export |vim9script|
20+
7. Classes and interfaces |vim9-classes|
2021

21-
9. Rationale |vim9-rationale|
22+
8. Rationale |vim9-rationale|
2223

2324
==============================================================================
2425

@@ -1895,7 +1896,146 @@ corresponding empty value.
18951896

18961897
==============================================================================
18971898

1898-
5. Namespace, Import and Export
1899+
*generic-functions*
1900+
5. Generic functions
1901+
1902+
A generic function allows using the same function with different type
1903+
arguments, while retaining type checking for arguments and the return value.
1904+
This provides type safety and code reusability.
1905+
1906+
Declaration~
1907+
*generic-function-declaration*
1908+
*E1553* *E1554* *E1559*
1909+
The type parameters for a generic function are declared in angle brackets "<"
1910+
and ">" directly after the function name. Multiple type names are separated
1911+
by commas: >
1912+
1913+
def[!] {funcname}<{type} [, {types}]>([arguments])[: {return-type}]
1914+
{function body}
1915+
enddef
1916+
<
1917+
These type parameters can then be used like any other type within the function
1918+
signature and body. Example: >
1919+
1920+
def MyFunc<T, A, B>(param1: T): T
1921+
var f: A
1922+
var x = param1
1923+
return x
1924+
enddef
1925+
<
1926+
*type-variable-naming* *E1552*
1927+
The convention is to use a single uppercase letter for a type variable (e.g.,
1928+
T, A, X), although longer names are allowed. The name must start with an
1929+
uppercase letter.
1930+
1931+
*E1558* *E1560*
1932+
A function must be declared and used either as generic or as a regular
1933+
function - but not both.
1934+
1935+
*E1561*
1936+
A type variable name must not conflict with other defined names, such as class
1937+
names, type aliases, enum names, function names or other type variable names.
1938+
1939+
Calling a generic function~
1940+
*generic-function-call*
1941+
To call a generic function, specify the concrete types in "<" and ">"
1942+
between the function name and the argument list: >
1943+
1944+
MyFunc<number, string, list<number>>()
1945+
<
1946+
*E1555* *E1556* *E1557*
1947+
The number of concrete types provided when calling a generic function must
1948+
match the number of type variables in the function. An empty type list is not
1949+
allowed. Any Vim9 type (|vim9-types|) can be used as a concrete type in a
1950+
generic function.
1951+
1952+
Spaces are not allowed between the function name and "<", or between ">" and
1953+
the opening "(".
1954+
1955+
A generic function can be exported and imported like a regular function.
1956+
See |:export| and |:import|.
1957+
1958+
A generic function can be defined inside another regular or generic function.
1959+
1960+
Referencing type variables in generic types~
1961+
1962+
Instead of concrete types, type variables can be used with generic types.
1963+
This is useful for complex data structures like lists of dictionaries or
1964+
dictionaries of lists. Example: >
1965+
1966+
vim9script
1967+
1968+
def Flatten<T>(x: list<list<T>>): list<T>
1969+
var result: list<T> = []
1970+
for inner in x
1971+
result += inner
1972+
endfor
1973+
return result
1974+
enddef
1975+
1976+
echo Flatten<number>([[1, 2], [3]])
1977+
<
1978+
1979+
Generic class method~
1980+
1981+
A Vim9 class method can be a generic function: >
1982+
1983+
class A
1984+
def Foo<X, Y>()
1985+
enddef
1986+
endclass
1987+
var a = A.new()
1988+
a.Foo<number, string>()
1989+
<
1990+
*E1432* *E1433* *E1434*
1991+
A generic class method in a base class can be overridden by a generic method
1992+
in a child class. The number of type variables must match between both
1993+
methods. A concrete class method cannot be overridden by a generic method,
1994+
and vice versa.
1995+
1996+
Generic function reference~
1997+
1998+
A function reference (|Funcref|) can be a generic function. This allows for
1999+
creating factories of functions that operate on specific types: >
2000+
2001+
vim9script
2002+
2003+
def MakeEcho<T>(): func(T): T
2004+
return (x: T): T => x
2005+
enddef
2006+
2007+
var EchoNumber = MakeEcho<number>()
2008+
echo EchoNumber(123)
2009+
2010+
var EchoString = MakeEcho<string>()
2011+
echo EchoString('abc')
2012+
<
2013+
Compiling and Disassembling Generic functions~
2014+
2015+
The |:defcompile| command can be used to compile a generic function with a
2016+
specific list of concrete types: >
2017+
2018+
defcompile MyFunc<number, list<number>, dict<string>>
2019+
<
2020+
The |:disassemble| command can be used to list the instructions generated for
2021+
a generic function: >
2022+
2023+
disassemble MyFunc<string, dict<string>>
2024+
disassemble MyFunc<number, list<blob>>
2025+
<
2026+
Limitations and Future Work~
2027+
2028+
Currently, Vim does not support:
2029+
- Type inference for type variables: All types must be explicitly specified
2030+
when calling a generic function.
2031+
- Type constraints: It's not possible to restrict a type variable to a
2032+
specific class or interface (e.g., `T extends SomeInterface`).
2033+
- Default type arguments: Providing a default type for a type parameter
2034+
when not explicitly specified.
2035+
2036+
==============================================================================
2037+
2038+
6. Namespace, Import and Export
18992039
*vim9script* *vim9-export* *vim9-import*
19002040

19012041
A Vim9 script can be written to be imported. This means that some items are
@@ -2174,7 +2314,7 @@ Or: >
21742314
21752315
==============================================================================
21762316

2177-
6. Classes and interfaces *vim9-classes*
2317+
7. Classes and interfaces *vim9-classes*
21782318

21792319
In legacy script a Dictionary could be used as a kind-of object, by adding
21802320
members that are functions. However, this is quite inefficient and requires
@@ -2188,7 +2328,7 @@ functionality it is located in a separate help file: |vim9class.txt|.
21882328

21892329
==============================================================================
21902330

2191-
9. Rationale *vim9-rationale*
2331+
8. Rationale *vim9-rationale*
21922332

21932333
The :def command ~
21942334

src/Make_ami.mak

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ SRC += \
183183
vim9compile.c \
184184
vim9execute.c \
185185
vim9expr.c \
186+
vim9generics.c \
186187
vim9instr.c \
187188
vim9script.c \
188189
vim9type.c \

src/Make_cyg_ming.mak

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,7 @@ OBJ = \
895895
$(OUTDIR)/vim9compile.o \
896896
$(OUTDIR)/vim9execute.o \
897897
$(OUTDIR)/vim9expr.o \
898+
$(OUTDIR)/vim9generics.o \
898899
$(OUTDIR)/vim9instr.o \
899900
$(OUTDIR)/vim9script.o \
900901
$(OUTDIR)/vim9type.o \
@@ -1328,6 +1329,8 @@ $(OUTDIR)/vim9execute.o: vim9execute.c $(INCL) vim9.h
13281329

13291330
$(OUTDIR)/vim9expr.o: vim9expr.c $(INCL) vim9.h
13301331

1332+
$(OUTDIR)/vim9generics.o: vim9generics.c $(INCL) vim9.h
1333+
13311334
$(OUTDIR)/vim9instr.o: vim9instr.c $(INCL) vim9.h
13321335

13331336
$(OUTDIR)/vim9script.o: vim9script.c $(INCL) vim9.h

src/Make_mvc.mak

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,7 @@ OBJ = \
803803
$(OUTDIR)\vim9compile.obj \
804804
$(OUTDIR)\vim9execute.obj \
805805
$(OUTDIR)\vim9expr.obj \
806+
$(OUTDIR)\vim9generics.obj \
806807
$(OUTDIR)\vim9instr.obj \
807808
$(OUTDIR)\vim9script.obj \
808809
$(OUTDIR)\vim9type.obj \
@@ -1824,6 +1825,8 @@ $(OUTDIR)/vim9execute.obj: $(OUTDIR) vim9execute.c $(INCL) vim9.h
18241825

18251826
$(OUTDIR)/vim9expr.obj: $(OUTDIR) vim9expr.c $(INCL) vim9.h
18261827

1828+
$(OUTDIR)/vim9generics.obj: $(OUTDIR) vim9generics.c $(INCL) vim9.h
1829+
18271830
$(OUTDIR)/vim9instr.obj: $(OUTDIR) vim9instr.c $(INCL) vim9.h
18281831

18291832
$(OUTDIR)/vim9script.obj: $(OUTDIR) vim9script.c $(INCL) vim9.h
@@ -2028,6 +2031,7 @@ proto.h: \
20282031
proto/vim9compile.pro \
20292032
proto/vim9execute.pro \
20302033
proto/vim9expr.pro \
2034+
proto/vim9generics.pro \
20312035
proto/vim9instr.pro \
20322036
proto/vim9script.pro \
20332037
proto/vim9type.pro \

src/Make_vms.mms

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ SRC = \
446446
vim9compile.c \
447447
vim9execute.c \
448448
vim9expr.c \
449+
vim9generics.c \
449450
vim9instr.c \
450451
vim9script.c \
451452
vim9type.c \
@@ -582,6 +583,7 @@ OBJ = \
582583
vim9compile.obj \
583584
vim9execute.obj \
584585
vim9expr.obj \
586+
vim9generics.obj \
585587
vim9instr.obj \
586588
vim9script.obj \
587589
vim9type.obj \
@@ -1225,6 +1227,10 @@ vim9expr.obj : vim9expr.c vim.h [.auto]config.h feature.h os_unix.h \
12251227
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
12261228
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
12271229
errors.h globals.h version.h
1230+
vim9generics.obj : vim9generics.c vim.h [.auto]config.h feature.h os_unix.h \
1231+
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
1232+
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \
1233+
errors.h globals.h version.h
12281234
vim9instr.obj : vim9instr.c vim.h [.auto]config.h feature.h os_unix.h \
12291235
ascii.h keymap.h termdefs.h macros.h structs.h regexp.h \
12301236
gui.h beval.h [.proto]gui_beval.pro option.h ex_cmds.h proto.h \

src/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,7 @@ BASIC_SRC = \
15981598
vim9compile.c \
15991599
vim9execute.c \
16001600
vim9expr.c \
1601+
vim9generics.c \
16011602
vim9instr.c \
16021603
vim9script.c \
16031604
vim9type.c \
@@ -1771,6 +1772,7 @@ OBJ_COMMON = \
17711772
objects/vim9compile.o \
17721773
objects/vim9execute.o \
17731774
objects/vim9expr.o \
1775+
objects/vim9generics.o \
17741776
objects/vim9instr.o \
17751777
objects/vim9script.o \
17761778
objects/vim9type.o \
@@ -1967,6 +1969,7 @@ PRO_AUTO = \
19671969
vim9compile.pro \
19681970
vim9execute.pro \
19691971
vim9expr.pro \
1972+
vim9generics.pro \
19701973
vim9instr.pro \
19711974
vim9script.pro \
19721975
vim9type.pro \
@@ -3630,6 +3633,9 @@ objects/vim9execute.o: vim9execute.c
36303633
objects/vim9expr.o: vim9expr.c
36313634
$(CCC) -o $@ vim9expr.c
36323635

3636+
objects/vim9generics.o: vim9generics.c
3637+
$(CCC) -o $@ vim9generics.c
3638+
36333639
objects/vim9instr.o: vim9instr.c
36343640
$(CCC) -o $@ vim9instr.c
36353641

@@ -4357,6 +4363,11 @@ objects/vim9expr.o: vim9expr.c vim.h protodef.h auto/config.h feature.h os_unix.
43574363
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
43584364
libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
43594365
globals.h errors.h vim9.h
4366+
objects/vim9generics.o: vim9generics.c vim.h protodef.h auto/config.h feature.h \
4367+
os_unix.h auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h \
4368+
beval.h proto/gui_beval.pro structs.h regexp.h gui.h \
4369+
libvterm/include/vterm.h libvterm/include/vterm_keycodes.h alloc.h \
4370+
ex_cmds.h spell.h proto.h globals.h errors.h vim9.h
43604371
objects/vim9instr.o: vim9instr.c vim.h protodef.h auto/config.h feature.h \
43614372
os_unix.h auto/osdef.h ascii.h keymap.h termdefs.h macros.h option.h \
43624373
beval.h proto/gui_beval.pro structs.h regexp.h gui.h \

0 commit comments

Comments
 (0)