comparison src/evalfunc.c @ 17612:e259d11e2900 v8.1.1803

patch 8.1.1803: all builtin functions are global commit https://github.com/vim/vim/commit/ac92e25a33c37ec5becbfffeccda136c73b761ac Author: Bram Moolenaar <Bram@vim.org> Date: Sat Aug 3 21:58:38 2019 +0200 patch 8.1.1803: all builtin functions are global Problem: All builtin functions are global. Solution: Add the method call operator ->. Implemented for a limited number of functions.
author Bram Moolenaar <Bram@vim.org>
date Sat, 03 Aug 2019 22:00:07 +0200
parents 1348696d07cd
children 072efa9ca875
comparison
equal deleted inserted replaced
17611:b9a3d542a042 17612:e259d11e2900
410 410
411 /* 411 /*
412 * Array with names and number of arguments of all internal functions 412 * Array with names and number of arguments of all internal functions
413 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH! 413 * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH!
414 */ 414 */
415 static struct fst 415 typedef struct
416 { 416 {
417 char *f_name; /* function name */ 417 char *f_name; /* function name */
418 char f_min_argc; /* minimal number of arguments */ 418 char f_min_argc; /* minimal number of arguments */
419 char f_max_argc; /* maximal number of arguments */ 419 char f_max_argc; /* maximal number of arguments */
420 void (*f_func)(typval_T *args, typval_T *rvar); 420 void (*f_func)(typval_T *args, typval_T *rvar);
421 /* implementation of function */ 421 /* implementation of function */
422 } functions[] = 422 } funcentry_T;
423
424 static funcentry_T global_functions[] =
423 { 425 {
424 #ifdef FEAT_FLOAT 426 #ifdef FEAT_FLOAT
425 {"abs", 1, 1, f_abs}, 427 {"abs", 1, 1, f_abs},
426 {"acos", 1, 1, f_acos}, /* WJMc */ 428 {"acos", 1, 1, f_acos}, /* WJMc */
427 #endif 429 #endif
985 {"wordcount", 0, 0, f_wordcount}, 987 {"wordcount", 0, 0, f_wordcount},
986 {"writefile", 2, 3, f_writefile}, 988 {"writefile", 2, 3, f_writefile},
987 {"xor", 2, 2, f_xor}, 989 {"xor", 2, 2, f_xor},
988 }; 990 };
989 991
992 /*
993 * Methods that call the internal function with the base as the first argument.
994 */
995 static funcentry_T base_methods[] =
996 {
997 {"add", 1, 1, f_add},
998 {"copy", 0, 0, f_copy},
999 {"count", 1, 3, f_count},
1000 {"empty", 0, 0, f_empty},
1001 {"extend", 1, 2, f_extend},
1002 {"filter", 1, 1, f_filter},
1003 {"get", 1, 2, f_get},
1004 {"index", 1, 3, f_index},
1005 {"insert", 1, 2, f_insert},
1006 {"items", 0, 0, f_items},
1007 {"join", 0, 1, f_join},
1008 {"keys", 0, 0, f_keys},
1009 {"len", 0, 0, f_len},
1010 {"map", 1, 1, f_map},
1011 {"max", 0, 0, f_max},
1012 {"min", 0, 0, f_min},
1013 {"remove", 1, 2, f_remove},
1014 {"repeat", 1, 1, f_repeat},
1015 {"reverse", 0, 0, f_reverse},
1016 {"sort", 0, 2, f_sort},
1017 {"string", 0, 0, f_string},
1018 {"type", 0, 0, f_type},
1019 {"uniq", 0, 2, f_uniq},
1020 {"values", 0, 0, f_values},
1021 };
1022
990 #if defined(FEAT_CMDL_COMPL) || defined(PROTO) 1023 #if defined(FEAT_CMDL_COMPL) || defined(PROTO)
991 1024
992 /* 1025 /*
993 * Function given to ExpandGeneric() to obtain the list of internal 1026 * Function given to ExpandGeneric() to obtain the list of internal
994 * or user defined function names. 1027 * or user defined function names.
1005 { 1038 {
1006 name = get_user_func_name(xp, idx); 1039 name = get_user_func_name(xp, idx);
1007 if (name != NULL) 1040 if (name != NULL)
1008 return name; 1041 return name;
1009 } 1042 }
1010 if (++intidx < (int)(sizeof(functions) / sizeof(struct fst))) 1043 if (++intidx < (int)(sizeof(global_functions) / sizeof(funcentry_T)))
1011 { 1044 {
1012 STRCPY(IObuff, functions[intidx].f_name); 1045 STRCPY(IObuff, global_functions[intidx].f_name);
1013 STRCAT(IObuff, "("); 1046 STRCAT(IObuff, "(");
1014 if (functions[intidx].f_max_argc == 0) 1047 if (global_functions[intidx].f_max_argc == 0)
1015 STRCAT(IObuff, ")"); 1048 STRCAT(IObuff, ")");
1016 return IObuff; 1049 return IObuff;
1017 } 1050 }
1018 1051
1019 return NULL; 1052 return NULL;
1041 } 1074 }
1042 1075
1043 #endif /* FEAT_CMDL_COMPL */ 1076 #endif /* FEAT_CMDL_COMPL */
1044 1077
1045 /* 1078 /*
1046 * Find internal function in table above. 1079 * Find internal function in table "functions".
1047 * Return index, or -1 if not found 1080 * Return index, or -1 if not found
1048 */ 1081 */
1049 int 1082 static int
1050 find_internal_func( 1083 find_internal_func(
1051 char_u *name) /* name of the function */ 1084 char_u *name, // name of the function
1085 funcentry_T *functions) // functions table to use
1052 { 1086 {
1053 int first = 0; 1087 int first = 0;
1054 int last = (int)(sizeof(functions) / sizeof(struct fst)) - 1; 1088 int last;
1055 int cmp; 1089 int cmp;
1056 int x; 1090 int x;
1057 1091
1058 /* 1092 if (functions == global_functions)
1059 * Find the function name in the table. Binary search. 1093 last = (int)(sizeof(global_functions) / sizeof(funcentry_T)) - 1;
1060 */ 1094 else
1095 last = (int)(sizeof(base_methods) / sizeof(funcentry_T)) - 1;
1096
1097 // Find the function name in the table. Binary search.
1061 while (first <= last) 1098 while (first <= last)
1062 { 1099 {
1063 x = first + ((unsigned)(last - first) >> 1); 1100 x = first + ((unsigned)(last - first) >> 1);
1064 cmp = STRCMP(name, functions[x].f_name); 1101 cmp = STRCMP(name, functions[x].f_name);
1065 if (cmp < 0) 1102 if (cmp < 0)
1071 } 1108 }
1072 return -1; 1109 return -1;
1073 } 1110 }
1074 1111
1075 int 1112 int
1113 has_internal_func(char_u *name)
1114 {
1115 return find_internal_func(name, global_functions) >= 0;
1116 }
1117
1118 int
1076 call_internal_func( 1119 call_internal_func(
1077 char_u *name, 1120 char_u *name,
1078 int argcount, 1121 int argcount,
1079 typval_T *argvars, 1122 typval_T *argvars,
1080 typval_T *rettv) 1123 typval_T *rettv)
1081 { 1124 {
1082 int i; 1125 int i;
1083 1126
1084 i = find_internal_func(name); 1127 i = find_internal_func(name, global_functions);
1085 if (i < 0) 1128 if (i < 0)
1086 return ERROR_UNKNOWN; 1129 return ERROR_UNKNOWN;
1087 if (argcount < functions[i].f_min_argc) 1130 if (argcount < global_functions[i].f_min_argc)
1088 return ERROR_TOOFEW; 1131 return ERROR_TOOFEW;
1089 if (argcount > functions[i].f_max_argc) 1132 if (argcount > global_functions[i].f_max_argc)
1090 return ERROR_TOOMANY; 1133 return ERROR_TOOMANY;
1091 argvars[argcount].v_type = VAR_UNKNOWN; 1134 argvars[argcount].v_type = VAR_UNKNOWN;
1092 functions[i].f_func(argvars, rettv); 1135 global_functions[i].f_func(argvars, rettv);
1136 return ERROR_NONE;
1137 }
1138
1139 /*
1140 * Invoke a method for base->method().
1141 */
1142 int
1143 call_internal_method(
1144 char_u *name,
1145 int argcount,
1146 typval_T *argvars,
1147 typval_T *rettv,
1148 typval_T *basetv)
1149 {
1150 int i;
1151 int fi;
1152 typval_T argv[MAX_FUNC_ARGS + 1];
1153
1154 fi = find_internal_func(name, base_methods);
1155 if (fi < 0)
1156 return ERROR_UNKNOWN;
1157 if (argcount < base_methods[fi].f_min_argc)
1158 return ERROR_TOOFEW;
1159 if (argcount > base_methods[fi].f_max_argc)
1160 return ERROR_TOOMANY;
1161
1162 argv[0] = *basetv;
1163 for (i = 0; i < argcount; ++i)
1164 argv[i + 1] = argvars[i];
1165 argv[argcount + 1].v_type = VAR_UNKNOWN;
1166
1167 base_methods[fi].f_func(argv, rettv);
1093 return ERROR_NONE; 1168 return ERROR_NONE;
1094 } 1169 }
1095 1170
1096 /* 1171 /*
1097 * Return TRUE for a non-zero Number and a non-empty String. 1172 * Return TRUE for a non-zero Number and a non-empty String.