Skip to content

Commit

Permalink
patch 9.0.2170: Vim9: no support for const/final class/objects vars
Browse files Browse the repository at this point in the history
Problem:  Vim9: no support for const/final class/objects vars
Solution: Support final and const object and class variables

closes: #13655

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
  • Loading branch information
yegappan authored and chrisbra committed Dec 16, 2023
1 parent d8bf87c commit e5437c5
Show file tree
Hide file tree
Showing 12 changed files with 835 additions and 22 deletions.
5 changes: 5 additions & 0 deletions runtime/doc/tags
Original file line number Diff line number Diff line change
Expand Up @@ -4505,7 +4505,10 @@ E1401 vim9class.txt /*E1401*
E1402 vim9class.txt /*E1402*
E1403 vim9class.txt /*E1403*
E1407 vim9class.txt /*E1407*
E1408 vim9class.txt /*E1408*
E1409 vim9class.txt /*E1409*
E141 message.txt /*E141*
E1410 vim9class.txt /*E1410*
E142 message.txt /*E142*
E143 autocmd.txt /*E143*
E144 various.txt /*E144*
Expand Down Expand Up @@ -9096,6 +9099,8 @@ o_V motion.txt /*o_V*
o_object-select motion.txt /*o_object-select*
o_v motion.txt /*o_v*
object vim9class.txt /*object*
object-const-variable vim9class.txt /*object-const-variable*
object-final-variable vim9class.txt /*object-final-variable*
object-motions motion.txt /*object-motions*
object-select motion.txt /*object-select*
objects index.txt /*objects*
Expand Down
3 changes: 1 addition & 2 deletions runtime/doc/todo.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*todo.txt* For Vim version 9.0. Last change: 2023 Jun 08
*todo.txt* For Vim version 9.0. Last change: 2023 Dec 14


VIM REFERENCE MANUAL by Bram Moolenaar
Expand Down Expand Up @@ -122,7 +122,6 @@ Upcoming larger works:

Further Vim9 improvements:
- Classes and Interfaces. See |vim9-classes|
- "final" object members - can only be set in the constructor.
- Cannot use class type of itself in the method (Issue #12369)
- Getting member of variable with "any" type should be handled at runtime.
Remove temporary solution from #12096 / patch 9.0.1375.
Expand Down
74 changes: 72 additions & 2 deletions runtime/doc/vim9class.txt
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,78 @@ super class. Depending on the class where the member is used the
corresponding class member will be used. The type of the class member in a
child class can be different from that in the super class.

*object-final-variable* *E1409*
The |:final| keyword can be used to make a class or object variable a
constant. Examples: >
class A
final v1 = [1, 2] # final object variable
public final v2 = {x: 1} # final object variable
static final v3 = 'abc' # final class variable
public static final v4 = 0z10 # final class variable
endclass
<
A final variable can be changed only from a constructor function. Example: >
class A
final v1: list<number>
def new()
this.v1 = [1, 2]
enddef
endclass
var a = A.new()
echo a.v1
<
Note that the value of a final variable can be changed. Example: >
class A
public final v1 = [1, 2]
endclass
var a = A.new()
a.v1[0] = 6 # OK
a.v1->add(3) # OK
a.v1 = [3, 4] # Error
<
*E1408*
Final variables are not supported in an interface. A class or object method
cannot be final.

*object-const-variable*
The |:const| keyword can be used to make a class or object variable and the
value a constant. Examples: >
class A
const v1 = [1, 2] # const object variable
public const v2 = {x: 1} # const object variable
static const v3 = 'abc' # const class variable
public static const v4 = 0z10 # const class variable
endclass
<
A const variable can be changed only from a constructor function. Example: >
class A
const v1: list<number>
def new()
this.v1 = [1, 2]
enddef
endclass
var a = A.new()
echo a.v1
<
A const variable and its value cannot be changed. Example: >
class A
public const v1 = [1, 2]
endclass
var a = A.new()
a.v1[0] = 6 # Error
a.v1->add(3) # Error
a.v1 = [3, 4] # Error
<
*E1410*
Const variables are not supported in an interface. A class or object method
cannot be a const.

==============================================================================

4. Using an abstract class *Vim9-abstract-class*
Expand Down Expand Up @@ -982,8 +1054,6 @@ function declaration syntax for class/object variables and methods. Vim9 also
reuses the general function declaration syntax for methods. So, for the sake
of consistency, we require "var" in these declarations.

This also allows for a natural use of "final" and "const" in the future.


Using "ClassName.new()" to construct an object ~

Expand Down
18 changes: 12 additions & 6 deletions src/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -3406,8 +3406,8 @@ EXTERN char e_invalid_class_variable_declaration_str[]
INIT(= N_("E1329: Invalid class variable declaration: %s"));
EXTERN char e_invalid_type_for_object_variable_str[]
INIT(= N_("E1330: Invalid type for object variable: %s"));
EXTERN char e_public_must_be_followed_by_var_or_static[]
INIT(= N_("E1331: Public must be followed by \"var\" or \"static\""));
EXTERN char e_public_must_be_followed_by_var_static_final_or_const[]
INIT(= N_("E1331: Public must be followed by \"var\" or \"static\" or \"final\" or \"const\""));
EXTERN char e_public_variable_name_cannot_start_with_underscore_str[]
INIT(= N_("E1332: Public variable name cannot start with underscore: %s"));
EXTERN char e_cannot_access_protected_variable_str[]
Expand Down Expand Up @@ -3488,8 +3488,8 @@ EXTERN char e_cannot_access_protected_method_str[]
INIT(= N_("E1366: Cannot access protected method: %s"));
EXTERN char e_variable_str_of_interface_str_has_different_access[]
INIT(= N_("E1367: Access level of variable \"%s\" of interface \"%s\" is different"));
EXTERN char e_static_must_be_followed_by_var_or_def[]
INIT(= N_("E1368: Static must be followed by \"var\" or \"def\""));
EXTERN char e_static_must_be_followed_by_var_def_final_or_const[]
INIT(= N_("E1368: Static must be followed by \"var\" or \"def\" or \"final\" or \"const\""));
EXTERN char e_duplicate_variable_str[]
INIT(= N_("E1369: Duplicate variable: %s"));
EXTERN char e_cannot_define_new_method_as_static[]
Expand Down Expand Up @@ -3568,8 +3568,14 @@ EXTERN char e_using_class_as_var_val[]
INIT(= N_("E1406: Cannot use a Class as a variable or value"));
EXTERN char e_using_typealias_as_var_val[]
INIT(= N_("E1407: Cannot use a Typealias as a variable or value"));
#endif
// E1408 - E1499 unused (reserved for Vim9 class support)
EXTERN char e_final_variable_not_supported_in_interface[]
INIT(= N_("E1408: Final variable not supported in an interface"));
EXTERN char e_cannot_change_readonly_variable_str_in_class_str[]
INIT(= N_("E1409: Cannot change read-only variable \"%s\" in class \"%s\""));
EXTERN char e_const_variable_not_supported_in_interface[]
INIT(= N_("E1410: Const variable not supported in an interface"));
#endif
// E1411 - E1499 unused (reserved for Vim9 class support)
EXTERN char e_cannot_mix_positional_and_non_positional_str[]
INIT(= N_("E1500: Cannot mix positional and non-positional arguments: %s"));
EXTERN char e_fmt_arg_nr_unused_str[]
Expand Down
7 changes: 7 additions & 0 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1778,6 +1778,13 @@ get_lval(
p, flags) == FAIL)
return NULL;

// When lhs is used to modify the variable, check it is
// not a read-only variable.
if ((flags & GLV_READ_ONLY) == 0
&& (*p != '.' && *p != '[')
&& oc_var_check_ro(cl, om))
return NULL;

lp->ll_valtype = om->ocm_type;

if (v_type == VAR_OBJECT)
Expand Down
2 changes: 2 additions & 0 deletions src/proto/vim9class.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ ocmember_T *member_lookup(class_T *cl, vartype_T v_type, char_u *name, size_t na
void emsg_var_cl_define(char *msg, char_u *name, size_t len, class_T *cl);
ufunc_T *method_lookup(class_T *cl, vartype_T v_type, char_u *name, size_t namelen, int *idx);
int inside_class(cctx_T *cctx_arg, class_T *cl);
int oc_var_check_ro(class_T *cl, ocmember_T *m);
void obj_lock_const_vars(object_T *obj);
void copy_object(typval_T *from, typval_T *to);
void copy_class(typval_T *from, typval_T *to);
void class_unref(class_T *cl);
Expand Down
6 changes: 5 additions & 1 deletion src/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1523,14 +1523,18 @@ typedef enum {
VIM_ACCESS_ALL // read/write everywhere
} omacc_T;

#define OCMFLAG_HAS_TYPE 0x01 // type specified explicitly
#define OCMFLAG_FINAL 0x02 // "final" object/class member
#define OCMFLAG_CONST 0x04 // "const" object/class member

/*
* Entry for an object or class member variable.
*/
typedef struct {
char_u *ocm_name; // allocated
omacc_T ocm_access;
int ocm_has_type; // type specified explicitly
type_T *ocm_type;
int ocm_flags;
char_u *ocm_init; // allocated
} ocmember_T;

Expand Down

0 comments on commit e5437c5

Please sign in to comment.