1 /*
2  *  gretl -- Gnu Regression, Econometrics and Time-series Library
3  *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 #include "libgretl.h"
21 #include "gretl_typemap.h"
22 
23 struct type_map {
24     GretlType std;     /* a "standard" type: non-array, non-reference */
25     GretlType stdref;  /* the "reference" form of the standard type, if any */
26     GretlType plural;  /* the associated array type, if any */
27     GretlType plref;   /* reference form of array type, if any */
28 };
29 
30 static struct type_map gretl_type_map[] = {
31     { GRETL_TYPE_MATRIX,   GRETL_TYPE_MATRIX_REF,
32       GRETL_TYPE_MATRICES, GRETL_TYPE_MATRICES_REF},
33     { GRETL_TYPE_BUNDLE,   GRETL_TYPE_BUNDLE_REF,
34       GRETL_TYPE_BUNDLES,  GRETL_TYPE_BUNDLES_REF},
35     { GRETL_TYPE_STRING,   GRETL_TYPE_STRING_REF,
36       GRETL_TYPE_STRINGS,  GRETL_TYPE_STRINGS_REF},
37     { GRETL_TYPE_ARRAY,    GRETL_TYPE_ARRAY_REF,
38       GRETL_TYPE_ARRAYS,   GRETL_TYPE_ARRAYS_REF},
39     { GRETL_TYPE_LIST,     GRETL_TYPE_LIST_REF,
40       GRETL_TYPE_LISTS,    GRETL_TYPE_LISTS_REF},
41     { GRETL_TYPE_SERIES,   GRETL_TYPE_SERIES_REF, 0, 0},
42     { GRETL_TYPE_DOUBLE,   GRETL_TYPE_SCALAR_REF, 0, 0}
43 };
44 
gretl_type_get_plural(GretlType type)45 GretlType gretl_type_get_plural (GretlType type)
46 {
47     int i, n = G_N_ELEMENTS(gretl_type_map);
48 
49     if (type == 0) return 0;
50 
51     for (i=0; i<n; i++) {
52 	if (type == gretl_type_map[i].std) {
53 	    return gretl_type_map[i].plural;
54 	}
55     }
56 
57     return 0;
58 }
59 
gretl_type_get_singular(GretlType type)60 GretlType gretl_type_get_singular (GretlType type)
61 {
62     int i, n = G_N_ELEMENTS(gretl_type_map);
63 
64     if (type == 0) return 0;
65 
66     for (i=0; i<n; i++) {
67 	if (type == gretl_type_map[i].plural) {
68 	    return gretl_type_map[i].std;
69 	}
70     }
71 
72     return 0;
73 }
74 
gretl_type_get_ref_type(GretlType type)75 GretlType gretl_type_get_ref_type (GretlType type)
76 {
77     int i, n = G_N_ELEMENTS(gretl_type_map);
78 
79     if (type == 0) return 0;
80 
81     for (i=0; i<n; i++) {
82 	if (type == gretl_type_map[i].std) {
83 	    return gretl_type_map[i].stdref;
84 	}
85 	if (type == gretl_type_map[i].plural) {
86 	    return gretl_type_map[i].plref;
87 	}
88 	if (type == gretl_type_map[i].stdref ||
89 	    type == gretl_type_map[i].plref) {
90 	    /* allow pass-through */
91 	    return type;
92 	}
93     }
94 
95     return 0;
96 }
97 
gretl_type_get_plain_type(GretlType type)98 GretlType gretl_type_get_plain_type (GretlType type)
99 {
100     int i, n = G_N_ELEMENTS(gretl_type_map);
101 
102     if (type == 0) return 0;
103 
104     for (i=0; i<n; i++) {
105 	if (type == gretl_type_map[i].stdref) {
106 	    return gretl_type_map[i].std;
107 	}
108 	if (type == gretl_type_map[i].plref) {
109 	    return gretl_type_map[i].plural;
110 	}
111 	if (type == gretl_type_map[i].std ||
112 	    type == gretl_type_map[i].plural) {
113 	    /* allow pass-through */
114 	    return type;
115 	}
116     }
117 
118     return 0;
119 }
120 
121 /**
122  * gretl_type_get_name:
123  * @type: a gretl type.
124  *
125  * Returns: the name of @type, or "invalid" on failure.
126  */
127 
gretl_type_get_name(GretlType type)128 const char *gretl_type_get_name (GretlType type)
129 {
130     switch (type) {
131     case GRETL_TYPE_BOOL:       return "bool";
132     case GRETL_TYPE_INT:        return "int";
133     case GRETL_TYPE_UNSIGNED:   return "unsigned";
134     case GRETL_TYPE_OBS:        return "obs";
135     case GRETL_TYPE_DOUBLE:     return "scalar";
136     case GRETL_TYPE_SERIES:     return "series";
137     case GRETL_TYPE_USERIES:    return "series";
138     case GRETL_TYPE_MATRIX:     return "matrix";
139     case GRETL_TYPE_LIST:       return "list";
140     case GRETL_TYPE_BUNDLE:     return "bundle";
141     case GRETL_TYPE_ARRAY:      return "array";
142     case GRETL_TYPE_STRING:     return "string";
143     case GRETL_TYPE_SCALAR_REF: return "scalar *";
144     case GRETL_TYPE_SERIES_REF: return "series *";
145     case GRETL_TYPE_MATRIX_REF: return "matrix *";
146     case GRETL_TYPE_BUNDLE_REF: return "bundle *";
147     case GRETL_TYPE_ARRAY_REF:  return "array *";
148     case GRETL_TYPE_STRING_REF: return "string *";
149     case GRETL_TYPE_LIST_REF:   return "list *";
150 
151     case GRETL_TYPE_STRINGS:      return "strings";
152     case GRETL_TYPE_MATRICES:     return "matrices";
153     case GRETL_TYPE_BUNDLES:      return "bundles";
154     case GRETL_TYPE_LISTS:        return "lists";
155     case GRETL_TYPE_ARRAYS:       return "arrays";
156 
157     case GRETL_TYPE_STRINGS_REF:  return "strings *";
158     case GRETL_TYPE_MATRICES_REF: return "matrices *";
159     case GRETL_TYPE_BUNDLES_REF:  return "bundles *";
160     case GRETL_TYPE_LISTS_REF:    return "lists *";
161     case GRETL_TYPE_ARRAYS_REF:   return "arrays *";
162 
163     case GRETL_TYPE_DATE:         return "date"; /* ODBC special */
164 
165     case GRETL_TYPE_VOID:       return "void";
166     case GRETL_TYPE_NUMERIC:    return "numeric";
167     case GRETL_TYPE_NONE:       return "null";
168     case GRETL_TYPE_ANY:        return "any";
169     default:
170 	return "invalid";
171     }
172 }
173 
gretl_type_from_string(const char * s)174 GretlType gretl_type_from_string (const char *s)
175 {
176     const char *p;
177 
178     if (!strncmp(s, "matrix", 6)) {
179 	p = s + 6;
180 	if (*p == '\0') {
181 	    return GRETL_TYPE_MATRIX;
182 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
183 	    return GRETL_TYPE_MATRIX_REF;
184 	}
185     } else if (!strncmp(s, "series", 6)) {
186 	p = s + 6;
187 	if (*p == '\0') {
188 	    return GRETL_TYPE_SERIES;
189 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
190 	    return GRETL_TYPE_SERIES_REF;
191 	}
192     } else if (!strncmp(s, "scalar", 6)) {
193 	p = s + 6;
194 	if (*p == '\0') {
195 	    return GRETL_TYPE_DOUBLE;
196 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
197 	    return GRETL_TYPE_SCALAR_REF;
198 	}
199     } else if (!strncmp(s, "bundle", 6)) {
200 	p = s + 6;
201 	if (*p == 's') {
202 	    p++;
203 	    if (*p == '\0') {
204 		return GRETL_TYPE_BUNDLES;
205 	    } else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
206 		return GRETL_TYPE_BUNDLES_REF;
207 	    }
208 	} else if (*p == '\0') {
209 	    return GRETL_TYPE_BUNDLE;
210 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
211 	    return GRETL_TYPE_BUNDLE_REF;
212 	}
213     } else if (!strncmp(s, "array", 5)) {
214 	p = s + 5;
215 	if (*p == 's') {
216 	    p++;
217 	    if (*p == '\0') {
218 		return GRETL_TYPE_ARRAYS;
219 	    } else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
220 		return GRETL_TYPE_ARRAYS_REF;
221 	    }
222 	} else if (*p == '\0') {
223 	    return GRETL_TYPE_ARRAY;
224 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
225 	    return GRETL_TYPE_ARRAY_REF;
226 	}
227     } else if (!strncmp(s, "string", 6)) {
228 	p = s + 6;
229 	if (*p == 's') {
230 	    p++;
231 	    if (*p == '\0') {
232 		return GRETL_TYPE_STRINGS;
233 	    } else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
234 		return GRETL_TYPE_STRINGS_REF;
235 	    }
236 	} else if (*p == '\0') {
237 	    return GRETL_TYPE_STRING;
238 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
239 	    return GRETL_TYPE_STRING_REF;
240 	}
241     } else if (!strncmp(s, "matrices", 8)) {
242 	p = s + 8;
243 	if (*p == '\0') {
244 	    return GRETL_TYPE_MATRICES;
245 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
246 	    return GRETL_TYPE_MATRICES_REF;
247 	}
248     } else if (!strncmp(s, "list", 4)) {
249 	p = s + 4;
250 	if (*p == 's') {
251 	    p++;
252 	    if (*p == '\0') {
253 		return GRETL_TYPE_LISTS;
254 	    } else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
255 		return GRETL_TYPE_LISTS_REF;
256 	    }
257 	} else if (*p == '\0') {
258 	    return GRETL_TYPE_LIST;
259 	} else if (!strcmp(p, " *") || !strcmp(p, "ref")) {
260 	    return GRETL_TYPE_LIST_REF;
261 	}
262     } else if (!strncmp(s, "numeric", 7)) {
263 	return GRETL_TYPE_NUMERIC;
264     } else {
265 	/* aliases */
266 	if (!strcmp(s, "bool"))     return GRETL_TYPE_BOOL;
267 	if (!strcmp(s, "boolean"))  return GRETL_TYPE_BOOL;
268 	if (!strcmp(s, "int"))      return GRETL_TYPE_INT;
269 	if (!strcmp(s, "unsigned")) return GRETL_TYPE_UNSIGNED;
270 	if (!strcmp(s, "obs"))      return GRETL_TYPE_OBS;
271     }
272 
273     return GRETL_TYPE_NONE;
274 }
275 
276 struct lookup {
277     const char *word;
278     GretlType type;
279 };
280 
281 static const struct lookup gentypes[] = {
282     { "series",   GRETL_TYPE_SERIES },
283     { "scalar",   GRETL_TYPE_DOUBLE },
284     { "matrix",   GRETL_TYPE_MATRIX },
285     { "string",   GRETL_TYPE_STRING },
286     { "list",     GRETL_TYPE_LIST },
287     { "bundle",   GRETL_TYPE_BUNDLE },
288     { "strings",  GRETL_TYPE_STRINGS },
289     { "matrices", GRETL_TYPE_MATRICES },
290     { "bundles",  GRETL_TYPE_BUNDLES },
291     { "lists",    GRETL_TYPE_LISTS },
292     { "arrays",   GRETL_TYPE_ARRAYS },
293 };
294 
gretl_get_gen_type(const char * s)295 GretlType gretl_get_gen_type (const char *s)
296 {
297     static GHashTable *ht;
298     gpointer p;
299     GretlType t = 0;
300 
301     if (s == NULL) {
302 	/* the clean-up signal */
303 	if (ht != NULL) {
304 	    g_hash_table_destroy(ht);
305 	    ht = NULL;
306 	}
307 	return 0;
308     }
309 
310     if (ht == NULL) {
311 	int i, n = G_N_ELEMENTS(gentypes);
312 
313 	ht = g_hash_table_new(g_str_hash, g_str_equal);
314 	for (i=0; i<n; i++) {
315 	    g_hash_table_insert(ht, (gpointer) gentypes[i].word,
316 				GINT_TO_POINTER(gentypes[i].type));
317 	}
318     }
319 
320     p = g_hash_table_lookup(ht, s);
321     if (p != NULL) {
322 	t = GPOINTER_TO_INT(p);
323     }
324 
325     return t;
326 }
327 
328 /* Note: this must agree with the doc for the typeof() function */
329 
gretl_type_get_order(GretlType type)330 int gretl_type_get_order (GretlType type)
331 {
332     if (gretl_scalar_type(type)) {
333         return 1;
334     } else if (type == GRETL_TYPE_SERIES) {
335         return 2;
336     } else if (type == GRETL_TYPE_MATRIX) {
337         return 3;
338     } else if (type == GRETL_TYPE_STRING) {
339         return 4;
340     } else if (type == GRETL_TYPE_BUNDLE) {
341         return 5;
342     } else if (type == GRETL_TYPE_ARRAY) {
343         return 6;
344     } else if (type == GRETL_TYPE_LIST) {
345         return 7;
346     } else {
347         return 0;
348     }
349 }
350 
gretl_is_array_type(GretlType type)351 int gretl_is_array_type (GretlType type)
352 {
353     return type == GRETL_TYPE_STRINGS ||
354 	type == GRETL_TYPE_MATRICES ||
355 	type == GRETL_TYPE_BUNDLES ||
356 	type == GRETL_TYPE_LISTS ||
357 	type == GRETL_TYPE_ARRAYS;
358 }
359 
gretl_is_arrayable_type(GretlType type)360 int gretl_is_arrayable_type (GretlType type)
361 {
362     return type == GRETL_TYPE_STRING ||
363 	type == GRETL_TYPE_MATRIX ||
364 	type == GRETL_TYPE_BUNDLE ||
365 	type == GRETL_TYPE_LIST ||
366 	type == GRETL_TYPE_ARRAY;
367 }
368 
gretl_is_scalar_type(GretlType type)369 int gretl_is_scalar_type (GretlType type)
370 {
371     return type == GRETL_TYPE_BOOL ||
372 	type == GRETL_TYPE_INT ||
373 	type == GRETL_TYPE_UNSIGNED ||
374 	type == GRETL_TYPE_DOUBLE;
375 }
376 
gretl_is_series_type(GretlType type)377 int gretl_is_series_type (GretlType type)
378 {
379     return type == GRETL_TYPE_SERIES ||
380 	type == GRETL_TYPE_USERIES;
381 }
382 
gretl_typemap_cleanup(void)383 void gretl_typemap_cleanup (void)
384 {
385     gretl_get_gen_type(NULL);
386 }
387