Mercurial > vim
comparison src/vim9class.c @ 33951:45a50fd59a73 v9.0.2170
patch 9.0.2170: Vim9: no support for const/final class/objects vars
Commit: https://github.com/vim/vim/commit/e5437c542709b77ade084f96e60d84d4e847e6d3
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Sat Dec 16 14:11:19 2023 +0100
patch 9.0.2170: Vim9: no support for const/final class/objects vars
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>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sat, 16 Dec 2023 14:15:05 +0100 |
parents | 3bba09502b8d |
children | 7c30841c60a0 |
comparison
equal
deleted
inserted
replaced
33950:ba10efba5843 | 33951:45a50fd59a73 |
---|---|
150 | 150 |
151 *type_ret = type; | 151 *type_ret = type; |
152 return OK; | 152 return OK; |
153 } | 153 } |
154 | 154 |
155 typedef struct oc_newmember_S oc_newmember_T; | |
156 struct oc_newmember_S | |
157 { | |
158 garray_T *gap; | |
159 char_u *varname; | |
160 char_u *varname_end; | |
161 int has_public; | |
162 int has_final; | |
163 int has_type; | |
164 type_T *type; | |
165 char_u *init_expr; | |
166 }; | |
167 | |
155 /* | 168 /* |
156 * Add a member to an object or a class. | 169 * Add a member to an object or a class. |
157 * Returns OK when successful, "init_expr" will be consumed then. | 170 * Returns OK when successful, "init_expr" will be consumed then. |
158 * Returns FAIL otherwise, caller might need to free "init_expr". | 171 * Returns FAIL otherwise, caller might need to free "init_expr". |
159 */ | 172 */ |
161 add_member( | 174 add_member( |
162 garray_T *gap, | 175 garray_T *gap, |
163 char_u *varname, | 176 char_u *varname, |
164 char_u *varname_end, | 177 char_u *varname_end, |
165 int has_public, | 178 int has_public, |
179 int has_final, | |
180 int has_const, | |
166 int has_type, | 181 int has_type, |
167 type_T *type, | 182 type_T *type, |
168 char_u *init_expr) | 183 char_u *init_expr) |
169 { | 184 { |
170 if (ga_grow(gap, 1) == FAIL) | 185 if (ga_grow(gap, 1) == FAIL) |
171 return FAIL; | 186 return FAIL; |
172 ocmember_T *m = ((ocmember_T *)gap->ga_data) + gap->ga_len; | 187 ocmember_T *m = ((ocmember_T *)gap->ga_data) + gap->ga_len; |
173 m->ocm_name = vim_strnsave(varname, varname_end - varname); | 188 m->ocm_name = vim_strnsave(varname, varname_end - varname); |
174 m->ocm_access = has_public ? VIM_ACCESS_ALL | 189 m->ocm_access = has_public ? VIM_ACCESS_ALL |
175 : *varname == '_' ? VIM_ACCESS_PRIVATE : VIM_ACCESS_READ; | 190 : *varname == '_' ? VIM_ACCESS_PRIVATE : VIM_ACCESS_READ; |
176 m->ocm_has_type = has_type; | 191 if (has_final) |
192 m->ocm_flags |= OCMFLAG_FINAL; | |
193 if (has_const) | |
194 m->ocm_flags |= OCMFLAG_CONST; | |
195 if (has_type) | |
196 m->ocm_flags |= OCMFLAG_HAS_TYPE; | |
177 m->ocm_type = type; | 197 m->ocm_type = type; |
178 if (init_expr != NULL) | 198 if (init_expr != NULL) |
179 m->ocm_init = init_expr; | 199 m->ocm_init = init_expr; |
180 ++gap->ga_len; | 200 ++gap->ga_len; |
181 return OK; | 201 return OK; |
1130 { | 1150 { |
1131 typval_T *etv = eval_expr(m->ocm_init, eap); | 1151 typval_T *etv = eval_expr(m->ocm_init, eap); |
1132 if (etv != NULL) | 1152 if (etv != NULL) |
1133 { | 1153 { |
1134 if (m->ocm_type->tt_type == VAR_ANY | 1154 if (m->ocm_type->tt_type == VAR_ANY |
1135 && !m->ocm_has_type | 1155 && !(m->ocm_flags & OCMFLAG_HAS_TYPE) |
1136 && etv->v_type != VAR_SPECIAL) | 1156 && etv->v_type != VAR_SPECIAL) |
1137 // If the member variable type is not yet set, then use | 1157 // If the member variable type is not yet set, then use |
1138 // the initialization expression type. | 1158 // the initialization expression type. |
1139 m->ocm_type = typval2type(etv, get_copyID(), | 1159 m->ocm_type = typval2type(etv, get_copyID(), |
1140 type_list_gap, | 1160 type_list_gap, |
1147 { | 1167 { |
1148 // TODO: proper default value | 1168 // TODO: proper default value |
1149 tv->v_type = m->ocm_type->tt_type; | 1169 tv->v_type = m->ocm_type->tt_type; |
1150 tv->vval.v_string = NULL; | 1170 tv->vval.v_string = NULL; |
1151 } | 1171 } |
1172 if (m->ocm_flags & OCMFLAG_CONST) | |
1173 item_lock(tv, DICT_MAXNEST, TRUE, TRUE); | |
1152 } | 1174 } |
1153 } | 1175 } |
1154 | 1176 |
1155 /* | 1177 /* |
1156 * Add a default constructor method (new()) to the class "cl". | 1178 * Add a default constructor method (new()) to the class "cl". |
1556 break; | 1578 break; |
1557 } | 1579 } |
1558 has_public = TRUE; | 1580 has_public = TRUE; |
1559 p = skipwhite(line + 6); | 1581 p = skipwhite(line + 6); |
1560 | 1582 |
1561 if (STRNCMP(p, "var", 3) != 0 && STRNCMP(p, "static", 6) != 0) | 1583 if (STRNCMP(p, "var", 3) != 0 && STRNCMP(p, "static", 6) != 0 |
1562 { | 1584 && STRNCMP(p, "final", 5) != 0 && STRNCMP(p, "const", 5) != 0) |
1563 emsg(_(e_public_must_be_followed_by_var_or_static)); | 1585 { |
1586 emsg(_(e_public_must_be_followed_by_var_static_final_or_const)); | |
1564 break; | 1587 break; |
1565 } | 1588 } |
1566 } | 1589 } |
1567 | 1590 |
1568 int abstract_method = FALSE; | 1591 int abstract_method = FALSE; |
1614 break; | 1637 break; |
1615 } | 1638 } |
1616 has_static = TRUE; | 1639 has_static = TRUE; |
1617 p = skipwhite(ps + 6); | 1640 p = skipwhite(ps + 6); |
1618 | 1641 |
1619 if (STRNCMP(p, "var", 3) != 0 && STRNCMP(p, "def", 3) != 0) | 1642 if (STRNCMP(p, "var", 3) != 0 && STRNCMP(p, "def", 3) != 0 |
1620 { | 1643 && STRNCMP(p, "final", 5) != 0 && STRNCMP(p, "const", 5) != 0) |
1621 emsg(_(e_static_must_be_followed_by_var_or_def)); | 1644 { |
1645 emsg(_(e_static_must_be_followed_by_var_def_final_or_const)); | |
1622 break; | 1646 break; |
1623 } | 1647 } |
1624 } | 1648 } |
1649 | |
1650 int has_final = FALSE; | |
1651 int has_var = FALSE; | |
1652 int has_const = FALSE; | |
1653 if (checkforcmd(&p, "var", 3)) | |
1654 has_var = TRUE; | |
1655 else if (checkforcmd(&p, "final", 5)) | |
1656 { | |
1657 if (!is_class) | |
1658 { | |
1659 emsg(_(e_final_variable_not_supported_in_interface)); | |
1660 break; | |
1661 } | |
1662 has_final = TRUE; | |
1663 } | |
1664 else if (checkforcmd(&p, "const", 5)) | |
1665 { | |
1666 if (!is_class) | |
1667 { | |
1668 emsg(_(e_const_variable_not_supported_in_interface)); | |
1669 break; | |
1670 } | |
1671 has_const = TRUE; | |
1672 } | |
1673 p = skipwhite(p); | |
1625 | 1674 |
1626 // object members (public, read access, private): | 1675 // object members (public, read access, private): |
1627 // "var _varname" | 1676 // "var _varname" |
1628 // "var varname" | 1677 // "var varname" |
1629 // "public var varname" | 1678 // "public var varname" |
1679 // "final _varname" | |
1680 // "final varname" | |
1681 // "public final varname" | |
1682 // "const _varname" | |
1683 // "const varname" | |
1684 // "public const varname" | |
1630 // class members (public, read access, private): | 1685 // class members (public, read access, private): |
1631 // "static var _varname" | 1686 // "static var _varname" |
1632 // "static var varname" | 1687 // "static var varname" |
1633 // "public static var varname" | 1688 // "public static var varname" |
1634 if (checkforcmd(&p, "var", 3)) | 1689 // "static final _varname" |
1690 // "static final varname" | |
1691 // "public static final varname" | |
1692 // "static const _varname" | |
1693 // "static const varname" | |
1694 // "public static const varname" | |
1695 if (has_var || has_final || has_const) | |
1635 { | 1696 { |
1636 char_u *varname = p; | 1697 char_u *varname = p; |
1637 char_u *varname_end = NULL; | 1698 char_u *varname_end = NULL; |
1638 type_T *type = NULL; | 1699 type_T *type = NULL; |
1639 char_u *init_expr = NULL; | 1700 char_u *init_expr = NULL; |
1669 varname_end)) | 1730 varname_end)) |
1670 { | 1731 { |
1671 vim_free(init_expr); | 1732 vim_free(init_expr); |
1672 break; | 1733 break; |
1673 } | 1734 } |
1674 if (add_member(has_static ? &classmembers : &objmembers, varname, varname_end, | 1735 if (add_member(has_static ? &classmembers : &objmembers, varname, |
1675 has_public, has_type, type, init_expr) == FAIL) | 1736 varname_end, has_public, has_final, has_const, |
1737 has_type, type, init_expr) == FAIL) | |
1676 { | 1738 { |
1677 vim_free(init_expr); | 1739 vim_free(init_expr); |
1678 break; | 1740 break; |
1679 } | 1741 } |
1680 } | 1742 } |
2778 return TRUE; | 2840 return TRUE; |
2779 return FALSE; | 2841 return FALSE; |
2780 } | 2842 } |
2781 | 2843 |
2782 /* | 2844 /* |
2845 * Return TRUE if object/class variable "m" is read-only. | |
2846 * Also give an error message. | |
2847 */ | |
2848 int | |
2849 oc_var_check_ro(class_T *cl, ocmember_T *m) | |
2850 { | |
2851 if (m->ocm_flags & (OCMFLAG_FINAL | OCMFLAG_CONST)) | |
2852 { | |
2853 semsg(_(e_cannot_change_readonly_variable_str_in_class_str), | |
2854 m->ocm_name, cl->class_name); | |
2855 return TRUE; | |
2856 } | |
2857 return FALSE; | |
2858 } | |
2859 | |
2860 /* | |
2861 * Lock all the constant object variables. Called after creating and | |
2862 * initializing a new object. | |
2863 */ | |
2864 void | |
2865 obj_lock_const_vars(object_T *obj) | |
2866 { | |
2867 for (int i = 0; i < obj->obj_class->class_obj_member_count; i++) | |
2868 { | |
2869 ocmember_T *ocm = &obj->obj_class->class_obj_members[i]; | |
2870 if (ocm->ocm_flags & OCMFLAG_CONST) | |
2871 { | |
2872 typval_T *mtv = ((typval_T *)(obj + 1)) + i; | |
2873 item_lock(mtv, DICT_MAXNEST, TRUE, TRUE); | |
2874 } | |
2875 } | |
2876 } | |
2877 | |
2878 /* | |
2783 * Make a copy of an object. | 2879 * Make a copy of an object. |
2784 */ | 2880 */ |
2785 void | 2881 void |
2786 copy_object(typval_T *from, typval_T *to) | 2882 copy_object(typval_T *from, typval_T *to) |
2787 { | 2883 { |