comparison src/vim9class.c @ 31416:f088f1d97eee v9.0.1041

patch 9.0.1041: cannot define a method in a class Commit: https://github.com/vim/vim/commit/ffdaca9e6f3d39af6857ac52ced9385df203a152 Author: Bram Moolenaar <Bram@vim.org> Date: Fri Dec 9 21:41:48 2022 +0000 patch 9.0.1041: cannot define a method in a class Problem: Cannot define a method in a class. Solution: Implement defining an object method. Make calling an object method work.
author Bram Moolenaar <Bram@vim.org>
date Fri, 09 Dec 2022 22:45:03 +0100
parents c82cb53474ee
children 462508d04341
comparison
equal deleted inserted replaced
31415:4fd33db887f2 31416:f088f1d97eee
75 garray_T objmembers; 75 garray_T objmembers;
76 ga_init2(&objmembers, sizeof(objmember_T), 10); 76 ga_init2(&objmembers, sizeof(objmember_T), 10);
77 77
78 // Growarray with object methods declared in the class. 78 // Growarray with object methods declared in the class.
79 garray_T objmethods; 79 garray_T objmethods;
80 ga_init2(&objmethods, sizeof(ufunc_T), 10); 80 ga_init2(&objmethods, sizeof(ufunc_T *), 10);
81 81
82 /* 82 /*
83 * Go over the body of the class until "endclass" is found. 83 * Go over the body of the class until "endclass" is found.
84 */ 84 */
85 char_u *theline = NULL; 85 char_u *theline = NULL;
95 // TODO: 95 // TODO:
96 // class members (public, read access, private): 96 // class members (public, read access, private):
97 // static varname 97 // static varname
98 // public static varname 98 // public static varname
99 // static _varname 99 // static _varname
100 //
101 // constructors:
102 // def new()
103 // enddef
104 // def newOther()
105 // enddef
106 //
107 // methods (object, class, generics):
108 // def someMethod()
109 // enddef
110 // static def someMethod()
111 // enddef
112 // def <Tval> someMethod()
113 // enddef
114 // static def <Tval> someMethod()
115 // enddef
116 100
117 char_u *p = line; 101 char_u *p = line;
118 if (checkforcmd(&p, "endclass", 4)) 102 if (checkforcmd(&p, "endclass", 4))
119 { 103 {
120 if (STRNCMP(line, "endclass", 8) != 0) 104 if (STRNCMP(line, "endclass", 8) != 0)
170 m->om_name = vim_strnsave(varname, varname_end - varname); 154 m->om_name = vim_strnsave(varname, varname_end - varname);
171 m->om_type = type; 155 m->om_type = type;
172 ++objmembers.ga_len; 156 ++objmembers.ga_len;
173 } 157 }
174 158
159 // constructors:
160 // def new()
161 // enddef
162 // def newOther()
163 // enddef
164 // methods:
165 // def someMethod()
166 // enddef
167 // TODO:
168 // static def someMethod()
169 // enddef
170 // def <Tval> someMethod()
171 // enddef
172 // static def <Tval> someMethod()
173 // enddef
174 else if (checkforcmd(&p, "def", 3))
175 {
176 exarg_T ea;
177 garray_T lines_to_free;
178
179 CLEAR_FIELD(ea);
180 ea.cmd = line;
181 ea.arg = p;
182 ea.cmdidx = CMD_def;
183 ea.getline = eap->getline;
184 ea.cookie = eap->cookie;
185
186 ga_init2(&lines_to_free, sizeof(char_u *), 50);
187 ufunc_T *uf = define_function(&ea, NULL, &lines_to_free, TRUE);
188 ga_clear_strings(&lines_to_free);
189
190 // TODO: how about errors?
191 if (uf != NULL && ga_grow(&objmethods, 1) == OK)
192 {
193 ((ufunc_T **)objmethods.ga_data)[objmethods.ga_len] = uf;
194 ++objmethods.ga_len;
195 }
196 }
197
175 else 198 else
176 { 199 {
177 semsg(_(e_not_valid_command_in_class_str), line); 200 semsg(_(e_not_valid_command_in_class_str), line);
178 break; 201 break;
179 } 202 }
204 sizeof(objmember_T) * objmembers.ga_len); 227 sizeof(objmember_T) * objmembers.ga_len);
205 vim_free(objmembers.ga_data); 228 vim_free(objmembers.ga_data);
206 229
207 int have_new = FALSE; 230 int have_new = FALSE;
208 for (int i = 0; i < objmethods.ga_len; ++i) 231 for (int i = 0; i < objmethods.ga_len; ++i)
209 if (STRCMP((((ufunc_T *)objmethods.ga_data) + i)->uf_name, 232 if (STRCMP(((ufunc_T **)objmethods.ga_data)[i]->uf_name,
210 "new") == 0) 233 "new") == 0)
211 { 234 {
212 have_new = TRUE; 235 have_new = TRUE;
213 break; 236 break;
214 } 237 }
235 fea.cmd = fea.arg = fga.ga_data; 258 fea.cmd = fea.arg = fga.ga_data;
236 259
237 garray_T lines_to_free; 260 garray_T lines_to_free;
238 ga_init2(&lines_to_free, sizeof(char_u *), 50); 261 ga_init2(&lines_to_free, sizeof(char_u *), 50);
239 262
240 ufunc_T *nf = define_function(&fea, NULL, &lines_to_free, cl); 263 ufunc_T *nf = define_function(&fea, NULL, &lines_to_free, TRUE);
241 264
242 ga_clear_strings(&lines_to_free); 265 ga_clear_strings(&lines_to_free);
243 vim_free(fga.ga_data); 266 vim_free(fga.ga_data);
244 267
245 if (nf != NULL && ga_grow(&objmethods, 1) == OK) 268 if (nf != NULL && ga_grow(&objmethods, 1) == OK)
246 { 269 {
247 ((ufunc_T **)objmethods.ga_data)[objmethods.ga_len] = nf; 270 ((ufunc_T **)objmethods.ga_data)[objmethods.ga_len] = nf;
248 ++objmethods.ga_len; 271 ++objmethods.ga_len;
249 272
250 nf->uf_flags |= FC_NEW; 273 nf->uf_flags |= FC_NEW;
251 nf->uf_class = cl;
252 nf->uf_ret_type = get_type_ptr(&type_list); 274 nf->uf_ret_type = get_type_ptr(&type_list);
253 if (nf->uf_ret_type != NULL) 275 if (nf->uf_ret_type != NULL)
254 { 276 {
255 nf->uf_ret_type->tt_type = VAR_OBJECT; 277 nf->uf_ret_type->tt_type = VAR_OBJECT;
256 nf->uf_ret_type->tt_member = (type_T *)cl; 278 nf->uf_ret_type->tt_member = (type_T *)cl;
257 nf->uf_ret_type->tt_argcount = 0; 279 nf->uf_ret_type->tt_argcount = 0;
258 nf->uf_ret_type->tt_args = NULL; 280 nf->uf_ret_type->tt_args = NULL;
259 } 281 }
260 cl->class_new_func = nf;
261 } 282 }
262 } 283 }
263 284
264 cl->class_obj_method_count = objmethods.ga_len; 285 cl->class_obj_method_count = objmethods.ga_len;
265 cl->class_obj_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len); 286 cl->class_obj_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len);
273 } 294 }
274 mch_memmove(cl->class_obj_methods, objmethods.ga_data, 295 mch_memmove(cl->class_obj_methods, objmethods.ga_data,
275 sizeof(ufunc_T *) * objmethods.ga_len); 296 sizeof(ufunc_T *) * objmethods.ga_len);
276 vim_free(objmethods.ga_data); 297 vim_free(objmethods.ga_data);
277 298
299 // Set the class pointer on all the object methods.
300 for (int i = 0; i < objmethods.ga_len; ++i)
301 {
302 ufunc_T *fp = cl->class_obj_methods[i];
303 fp->uf_class = cl;
304 fp->uf_flags |= FC_OBJECT; // TODO: not for class method
305 }
306
278 cl->class_type.tt_type = VAR_CLASS; 307 cl->class_type.tt_type = VAR_CLASS;
279 cl->class_type.tt_member = (type_T *)cl; 308 cl->class_type.tt_member = (type_T *)cl;
309 cl->class_object_type.tt_type = VAR_OBJECT;
310 cl->class_object_type.tt_member = (type_T *)cl;
280 cl->class_type_list = type_list; 311 cl->class_type_list = type_list;
281 312
282 // TODO: 313 // TODO:
283 // - Add the methods to the class 314 // - Add the methods to the class
284 // - array with ufunc_T pointers 315 // - array with ufunc_T pointers
303 objmember_T *m = ((objmember_T *)objmembers.ga_data) + i; 334 objmember_T *m = ((objmember_T *)objmembers.ga_data) + i;
304 vim_free(m->om_name); 335 vim_free(m->om_name);
305 } 336 }
306 ga_clear(&objmembers); 337 ga_clear(&objmembers);
307 338
339 for (int i = 0; i < objmethods.ga_len; ++i)
340 {
341 ufunc_T *uf = ((ufunc_T **)objmethods.ga_data)[i];
342 func_clear_free(uf, FALSE);
343 }
308 ga_clear(&objmethods); 344 ga_clear(&objmethods);
309 clear_type_list(&type_list); 345 clear_type_list(&type_list);
310 } 346 }
311 347
312 /* 348 /*
417 return FAIL; 453 return FAIL;
418 454
419 funcexe_T funcexe; 455 funcexe_T funcexe;
420 CLEAR_FIELD(funcexe); 456 CLEAR_FIELD(funcexe);
421 funcexe.fe_evaluate = TRUE; 457 funcexe.fe_evaluate = TRUE;
458 if (rettv->v_type == VAR_OBJECT)
459 {
460 funcexe.fe_object = rettv->vval.v_object;
461 ++funcexe.fe_object->obj_refcount;
462 }
422 463
423 // Clear the class or object after calling the function, in 464 // Clear the class or object after calling the function, in
424 // case the refcount is one. 465 // case the refcount is one.
425 typval_T tv_tofree = *rettv; 466 typval_T tv_tofree = *rettv;
426 rettv->v_type = VAR_UNKNOWN; 467 rettv->v_type = VAR_UNKNOWN;
427 468
428 // Call the user function. Result goes into rettv; 469 // Call the user function. Result goes into rettv;
429 // TODO: pass the object
430 int error = call_user_func_check(fp, argcount, argvars, 470 int error = call_user_func_check(fp, argcount, argvars,
431 rettv, &funcexe, NULL); 471 rettv, &funcexe, NULL);
432 472
433 // Clear the previous rettv and the arguments. 473 // Clear the previous rettv and the arguments.
434 clear_tv(&tv_tofree); 474 clear_tv(&tv_tofree);
543 objmember_T *m = &cl->class_obj_members[i]; 583 objmember_T *m = &cl->class_obj_members[i];
544 vim_free(m->om_name); 584 vim_free(m->om_name);
545 } 585 }
546 vim_free(cl->class_obj_members); 586 vim_free(cl->class_obj_members);
547 587
588 for (int i = 0; i < cl->class_obj_method_count; ++i)
589 {
590 ufunc_T *uf = cl->class_obj_methods[i];
591 func_clear_free(uf, FALSE);
592 }
548 vim_free(cl->class_obj_methods); 593 vim_free(cl->class_obj_methods);
549
550 if (cl->class_new_func != NULL)
551 func_ptr_unref(cl->class_new_func);
552 594
553 clear_type_list(&cl->class_type_list); 595 clear_type_list(&cl->class_type_list);
554 596
555 vim_free(cl); 597 vim_free(cl);
556 } 598 }