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 {