Mercurial > vim
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. |