Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : /*
14 : * (author) M. Kersten
15 : *
16 : * Search the first definition of the operator in the current module
17 : * and check the parameter types.
18 : * For a polymorphic MAL function we make a fully instantiated clone.
19 : * It will be prepended to the symbol list as it is more restrictive.
20 : * This effectively overloads the MAL procedure.
21 : */
22 : #include "monetdb_config.h"
23 : #include "mal_resolve.h"
24 : #include "mal_namespace.h"
25 : #include "mal_private.h"
26 : #include "mal_linker.h"
27 :
28 : static malType getPolyType(malType t, int *polytype);
29 : static int updateTypeMap(int formal, int actual, int polytype[MAXTYPEVAR]);
30 : static int typeKind(MalBlkPtr mb, InstrPtr p, int i);
31 :
32 : int
33 198824983 : resolvedType(int dsttype, int srctype)
34 : {
35 198824983 : if (dsttype == srctype || dsttype == TYPE_any || srctype == TYPE_any ||
36 119202732 : (isaBatType(srctype) && dsttype == TYPE_bat) ||
37 119202732 : (isaBatType(dsttype) && srctype == TYPE_bat))
38 : return 0;
39 :
40 81930107 : if (isaBatType(dsttype) && isaBatType(srctype)) {
41 81160791 : int t1 = getBatType(dsttype);
42 81160791 : int t2 = getBatType(srctype);
43 81160791 : if (t1 == t2 || t1 == TYPE_any || t2 == TYPE_any)
44 44003912 : return 0;
45 : }
46 : return -1;
47 : }
48 :
49 : static int
50 56618273 : resolveType(int *rtype, int dsttype, int srctype)
51 : {
52 56618273 : if (dsttype == srctype) {
53 25674518 : *rtype = dsttype;
54 25674518 : return 0;
55 : }
56 30943755 : if (dsttype == TYPE_any) {
57 3458845 : *rtype = srctype;
58 3458845 : return 0;
59 : }
60 27484910 : if (srctype == TYPE_any) {
61 19526853 : *rtype = dsttype;
62 19526853 : return 0;
63 : }
64 : /*
65 : * A bat reference can be coerced to bat type.
66 : */
67 7958057 : if (isaBatType(srctype) && dsttype == TYPE_bat) {
68 0 : *rtype = srctype;
69 0 : return 0;
70 : }
71 7958057 : if (isaBatType(dsttype) && srctype == TYPE_bat) {
72 1 : *rtype = dsttype;
73 1 : return 0;
74 : }
75 7929373 : if (isaBatType(dsttype) && isaBatType(srctype)) {
76 7929339 : int t1, t2, t3;
77 7929339 : t1 = getBatType(dsttype);
78 7929339 : t2 = getBatType(srctype);
79 7929339 : if (t1 == t2)
80 : t3 = t1;
81 7929336 : else if (t1 == TYPE_any)
82 : t3 = t2;
83 91218 : else if (t2 == TYPE_any)
84 : t3 = t1;
85 : else {
86 : return -1;
87 : }
88 7838127 : *rtype = newBatType(t3);
89 7838127 : return 0;
90 : }
91 : return -1;
92 : }
93 :
94 :
95 : /*
96 : * Since we now know the storage type of the receiving variable, we can
97 : * set the garbage collection flag.
98 : */
99 : #define prepostProcess(tp, p, b, mb) \
100 : do { \
101 : if( isaBatType(tp) || \
102 : ATOMtype(tp) == TYPE_str || \
103 : (!isPolyType(tp) && tp < TYPE_any && \
104 : tp >= 0 && ATOMextern(tp))) { \
105 : getInstrPtr(mb, 0)->gc |= GARBAGECONTROL; \
106 : setVarCleanup(mb, getArg(p, b)); \
107 : p->gc |= GARBAGECONTROL; \
108 : } \
109 : } while (0)
110 :
111 : static malType
112 54570844 : findFunctionType(Module scope, MalBlkPtr mb, InstrPtr p, int idx, int silent)
113 : {
114 54570844 : Module m;
115 54570844 : Symbol s;
116 54570844 : InstrPtr sig;
117 54570844 : int i, k, unmatched = 0, s1;
118 54570844 : int polytype[MAXTYPEVAR];
119 54570844 : int returns[256];
120 54570844 : int *returntype = NULL;
121 : /*
122 : * Within a module find the element in its list
123 : * of symbols. A skiplist is used to speed up the search for the
124 : * definition of the function.
125 : *
126 : * For the implementation we should be aware that over 90% of the
127 : * functions in the kernel have just a few arguments and a single
128 : * return value.
129 : * A point of concern is that polymorphic arithmetic operations
130 : * lead to an explosion in the symbol table. This increase the
131 : * loop to find a candidate.
132 : *
133 : * Consider to collect the argument type into a separate structure, because
134 : * it will be looked up multiple types to resolve the instruction.[todo]
135 : * Simplify polytype using a map into the concrete argument table.
136 : */
137 :
138 54570844 : m = scope;
139 54570844 : s = m->space[(int) (getSymbolIndex(getFunctionId(p)))];
140 54570844 : if (s == 0)
141 : return -1;
142 :
143 54570469 : if (p->retc < 256) {
144 112572068 : for (i = 0; i < p->retc; i++)
145 58001639 : returns[i] = 0;
146 54570469 : returntype = returns;
147 : } else {
148 40 : returntype = (int *) GDKzalloc(p->retc * sizeof(int));
149 40 : if (returntype == 0)
150 : return -1;
151 : }
152 :
153 359726771 : while (s != NULL) { /* single scope element check */
154 359726070 : if (getFunctionId(p) != s->name) {
155 102925102 : s = s->skip;
156 102925102 : continue;
157 : }
158 : /*
159 : * Perform a strong type-check on the actual arguments. If it
160 : * turns out to be a polymorphic MAL function, we have to
161 : * clone it. Provided the actual/formal parameters are
162 : * compliant throughout the function call.
163 : *
164 : * Also look out for variable argument lists. This means that
165 : * we have to keep two iterators, one for the caller (i) and
166 : * one for the callee (k). Since a variable argument only
167 : * occurs as the last one, we simple avoid an increment when
168 : * running out of formal arguments.
169 : *
170 : * A call of the form (X1,..., Xi) := f(Y1,....,Yn) can be
171 : * matched against the function signature (B1,...,Bk):=
172 : * f(A1,...,Am) where i==k , n<=m and
173 : * type(Ai)=type(Yi). Furthermore, the variables Xi obtain
174 : * their type from Bi (or type(Bi)==type(Xi)).
175 : */
176 256800968 : sig = getSignature(s);
177 256800968 : unmatched = 0;
178 :
179 : /*
180 : * The simple case could be taken care of separately to
181 : * speedup processing
182 : * However, it turned out not to make a big difference. The
183 : * first time we encounter a polymorphic argument in the
184 : * signature.
185 : * Subsequently, the polymorphic arguments update this table
186 : * and check for any type mismatches that might occur. There
187 : * are at most 2 type variables involved per argument due to
188 : * the limited type nesting permitted. Note, each function
189 : * returns at least one value.
190 : */
191 256800968 : if (sig->polymorphic) {
192 77265015 : int limit = sig->polymorphic;
193 77265015 : if (!(sig->argc == p->argc ||
194 9086148 : (sig->argc < p->argc && sig->varargs & (VARARGS | VARRETS)))
195 : ) {
196 37587919 : s = s->peer;
197 37587919 : continue;
198 : }
199 39677096 : if (sig->retc != p->retc && !(sig->varargs & VARRETS)) {
200 312729 : s = s->peer;
201 312729 : continue;
202 : }
203 :
204 312745459 : for (k = 0; k < limit; k++)
205 273381092 : polytype[k] = TYPE_any;
206 : /*
207 : * Most polymorphic functions don't have a variable argument
208 : * list. So we save some instructions factoring this caise out.
209 : * Be careful, the variable number of return arguments should
210 : * be considered as well.
211 : */
212 : i = p->retc;
213 : /* first handle the variable argument list */
214 178775780 : for (k = sig->retc; i < p->argc; k++, i++) {
215 147215780 : int actual = getArgType(mb, p, i);
216 147215780 : int formal = getArgType(s->def, sig, k);
217 147215780 : if (k == sig->argc - 1 && sig->varargs & VARARGS)
218 54230945 : k--;
219 : /*
220 : * Take care of variable argument lists.
221 : * They are allowed as the last in the signature only.
222 : * Furthermore, for patterns if the formal type is
223 : * 'any' then all remaining arguments are acceptable
224 : * and detailed type analysis becomes part of the
225 : * pattern implementation.
226 : * In all other cases the type should apply to all
227 : * remaining arguments.
228 : */
229 147215780 : if (formal == actual)
230 52318340 : continue;
231 94897440 : if (updateTypeMap(formal, actual, polytype)) {
232 : unmatched = i;
233 : break;
234 : }
235 92673600 : formal = getPolyType(formal, polytype);
236 : /*
237 : * Collect the polymorphic types and resolve them.
238 : * If it fails, we know this isn't the function we are
239 : * looking for.
240 : */
241 92673600 : if (resolvedType(formal, actual) < 0) {
242 : unmatched = i;
243 : break;
244 : }
245 : }
246 : /*
247 : * The last argument/result type could be a polymorphic
248 : * variable list. It should only be allowed for patterns,
249 : * where it can deal with the stack. If the type is
250 : * specified as :any then any mix of arguments is allowed.
251 : * If the type is a new numbered type variable then the
252 : * first element in the list determines the required type
253 : * of all.
254 : */
255 39364114 : if (sig->varargs) {
256 6790924 : if (sig->token != PATTERNsymbol)
257 : unmatched = i;
258 : else {
259 : /* resolve the arguments */
260 6792749 : for (; i < p->argc; i++) {
261 : /* the type of the last one has already been set */
262 1452884 : int actual = getArgType(mb, p, i);
263 1452884 : int formal = getArgType(s->def, sig, k);
264 1452884 : if (k == sig->argc - 1 && sig->varargs & VARARGS)
265 0 : k--;
266 :
267 1452884 : formal = getPolyType(formal, polytype);
268 1452884 : if (formal == actual || formal == TYPE_any)
269 1044 : continue;
270 1451840 : if (resolvedType(formal, actual) < 0) {
271 : unmatched = i;
272 : break;
273 : }
274 : }
275 : }
276 : }
277 : } else {
278 : /*
279 : * We have to check the argument types to determine a
280 : * possible match for the non-polymorphic case.
281 : */
282 179535953 : if (sig->argc != p->argc || sig->retc != p->retc) {
283 91031484 : s = s->peer;
284 91031484 : continue;
285 : }
286 :
287 :
288 127847600 : for (i = p->retc; i < p->argc; i++) {
289 104717429 : int actual = getArgType(mb, p, i);
290 104717429 : int formal = getArgType(s->def, sig, i);
291 104717429 : if (resolvedType(formal, actual) < 0) {
292 : unmatched = i;
293 : break;
294 : }
295 : }
296 : }
297 : /*
298 : * It is possible that you may have to coerce the value to
299 : * another type. We assume that coercions are explicit at the
300 : * MAL level. (e.g. var2:= var0:int). This avoids repeated
301 : * type analysis just before you execute a function.
302 : * An optimizer may at a later stage automatically insert such
303 : * coercion requests.
304 : */
305 :
306 127870163 : if (unmatched) {
307 73179144 : s = s->peer;
308 73179144 : continue;
309 : }
310 : /*
311 : * At this stage we know all arguments are type compatible
312 : * with the signature.
313 : * We should assure that also the target variables have the
314 : * proper types or can inherit them from the signature. The
315 : * result type vector should be build separately first,
316 : * because we may encounter an error later on.
317 : *
318 : * If any of the arguments refer to a constraint type, any_x,
319 : * then the resulting type can not be determined.
320 : */
321 54691019 : s1 = 0;
322 54691019 : if (sig->polymorphic)
323 66212628 : for (k = i = 0; i < p->retc; k++, i++) {
324 34661514 : int actual = getArgType(mb, p, i);
325 34661514 : int formal = getArgType(s->def, sig, k);
326 :
327 34661514 : if (k == sig->retc - 1 && sig->varargs & VARRETS)
328 337982 : k--;
329 :
330 34661514 : s1 = getPolyType(formal, polytype);
331 :
332 34661514 : if (resolveType(returntype+i, s1, actual) < 0) {
333 : s1 = -1;
334 : break;
335 : }
336 : } else
337 : /* check for non-polymorphic return */
338 46505615 : for (k = i = 0; i < p->retc; i++) {
339 23498735 : int actual = getArgType(mb, p, i);
340 23498735 : int formal = getArgType(s->def, sig, i);
341 :
342 23498735 : if (k == sig->retc - 1 && sig->varargs & VARRETS)
343 : k--;
344 :
345 23498735 : if (actual == formal)
346 8819661 : returntype[i] = actual;
347 : else {
348 14679074 : if (resolveType(returntype+i, formal, actual) < 0) {
349 : s1 = -1;
350 : break;
351 : }
352 : }
353 : }
354 54677918 : if (s1 < 0) {
355 119924 : s = s->peer;
356 119924 : continue;
357 : }
358 : /*
359 : * If the return types are correct, copy them in place.
360 : * Beware that signatures should be left untouched, which
361 : * means that we may not overwrite any formal argument.
362 : * Using the knowledge dat the arguments occupy the header
363 : * of the symbol stack, it is easy to filter such errors.
364 : * Also mark all variables that are subject to garbage control.
365 : * Beware, this is not yet effectuated in the interpreter.
366 : */
367 :
368 54557994 : p->typechk = TYPE_RESOLVED;
369 112585876 : for (i = 0; i < p->retc; i++) {
370 58027882 : int ts = returntype[i];
371 58027882 : if (isVarConstant(mb, getArg(p, i))) {
372 0 : if (!silent) {
373 0 : mb->errors = createMalException(mb, idx, TYPE,
374 : "Assignment to constant");
375 : }
376 0 : p->typechk = TYPE_UNKNOWN;
377 0 : goto wrapup;
378 : }
379 58027882 : if (!isVarFixed(mb, getArg(p, i)) && ts >= 0) {
380 30561277 : setVarType(mb, getArg(p, i), ts);
381 30561277 : setVarFixed(mb, getArg(p, i));
382 : }
383 58027882 : prepostProcess(ts, p, i, mb);
384 : }
385 : /*
386 : * Also the arguments may contain constants
387 : * to be garbage collected.
388 : */
389 223862081 : for (i = p->retc; i < p->argc; i++)
390 169304087 : if (ATOMtype(getArgType(mb, p, i)) == TYPE_str ||
391 131573792 : getArgType(mb, p, i) == TYPE_bat ||
392 131573792 : isaBatType(getArgType(mb, p, i)) ||
393 40051584 : (!isPolyType(getArgType(mb, p, i)) &&
394 40051567 : getArgType(mb, p, i) < TYPE_any &&
395 40051567 : getArgType(mb, p, i) >= 0 &&
396 40051567 : ATOMstorage(getArgType(mb, p, i)) == TYPE_str)) {
397 129255659 : getInstrPtr(mb, 0)->gc |= GARBAGECONTROL;
398 129255659 : p->gc |= GARBAGECONTROL;
399 : }
400 : /*
401 : * It may happen that an argument was still untyped and as a
402 : * result of the polymorphism matching became strongly
403 : * typed. This should be reflected in the symbol table.
404 : */
405 54557994 : s1 = returntype[0]; /* for those interested */
406 : /*
407 : * If the call refers to a polymorphic function, we clone it
408 : * to arrive at a bounded instance. Polymorphic patterns and
409 : * commands are responsible for type resolution themselves.
410 : * Note that cloning pre-supposes that the function being
411 : * cloned does not contain errors detected earlier in the
412 : * process, nor does it contain polymorphic actual arguments.
413 : */
414 54557994 : if (sig->polymorphic) {
415 : int cnt = 0;
416 167120178 : for (k = i = p->retc; i < p->argc; i++) {
417 135567197 : int actual = getArgType(mb, p, i);
418 135567197 : if (isAnyExpression(actual))
419 10 : cnt++;
420 : }
421 31552981 : if (cnt == 0 && s->kind != COMMANDsymbol
422 16027042 : && s->kind != PATTERNsymbol) {
423 18 : s = cloneFunction(scope, s, mb, p);
424 18 : if (mb->errors)
425 3 : goto wrapup;
426 : }
427 : }
428 : /* Any previousely found error in the block
429 : * turns the complete block into erroneous.
430 : if (mb->errors) {
431 : p->typechk = TYPE_UNKNOWN;
432 : goto wrapup;
433 : }
434 : */
435 :
436 : /*
437 : * We found the proper function. Copy some properties. In
438 : * particular, determine the calling strategy, i.e. FCNcall,
439 : * CMDcall, PATcall Beware that polymorphic functions
440 : * may produce type-incorrect clones. This piece of code may be
441 : * shared by the separate binder
442 : */
443 54557991 : if (p->token == ASSIGNsymbol) {
444 54566561 : switch (getSignature(s)->token) {
445 17077719 : case COMMANDsymbol:
446 17077719 : p->token = CMDcall;
447 17077719 : p->fcn = getSignature(s)->fcn; /* C implementation mandatory */
448 17077719 : if (p->fcn == NULL) {
449 1 : if (!silent)
450 1 : mb->errors = createMalException(mb, idx, TYPE,
451 : "object code for command %s.%s missing",
452 : p->modname, p->fcnname);
453 1 : p->typechk = TYPE_UNKNOWN;
454 1 : goto wrapup;
455 : }
456 : break;
457 37478775 : case PATTERNsymbol:
458 37478775 : p->token = PATcall;
459 37478775 : p->fcn = getSignature(s)->fcn; /* C implementation optional */
460 37478775 : break;
461 10067 : case FUNCTIONsymbol:
462 10067 : p->token = FCNcall;
463 10067 : if (getSignature(s)->fcn)
464 0 : p->fcn = getSignature(s)->fcn; /* C implementation optional */
465 : break;
466 0 : default:
467 0 : if (!silent)
468 0 : mb->errors = createMalException(mb, idx, MAL,
469 : "MALresolve: unexpected token type");
470 0 : goto wrapup;
471 : }
472 54566560 : p->blk = s->def;
473 : }
474 :
475 54557990 : if (returntype != returns)
476 40 : GDKfree(returntype);
477 : return s1;
478 : } /* while */
479 : /*
480 : * We haven't found the correct function. To ease debugging, we
481 : * may reveal that we found an instruction with the proper
482 : * arguments, but that clashes with one of the target variables.
483 : */
484 701 : wrapup:
485 705 : if (returntype != returns)
486 0 : GDKfree(returntype);
487 : return -3;
488 : }
489 :
490 : /*
491 : * We try to clear the type check flag by looking up the
492 : * functions. Errors are simply ignored at this point of the game,
493 : * because they may be resolved as part of the calling sequence.
494 : */
495 : static void
496 5 : typeMismatch(MalBlkPtr mb, InstrPtr p, int idx, int lhs, int rhs, int silent)
497 : {
498 5 : str n1;
499 5 : str n2;
500 :
501 5 : if (!silent) {
502 5 : n1 = getTypeName(lhs);
503 5 : n2 = getTypeName(rhs);
504 5 : mb->errors = createMalException(mb, idx, TYPE, "type mismatch %s := %s", n1,
505 : n2);
506 5 : GDKfree(n1);
507 5 : GDKfree(n2);
508 : }
509 5 : p->typechk = TYPE_UNKNOWN;
510 5 : }
511 :
512 : /*
513 : * A function search should inspect all modules unless a specific module
514 : * is given. Preference is given to the lower scopes.
515 : * The type check is set to TYPE_UNKNOWN first to enforce a proper
516 : * analysis. This way it forms a cheap mechanism to resolve
517 : * the type after a change by an optimizer.
518 : * If we can not find the function, the type check returns unsuccessfully.
519 : * In this case we should issue an error message to the user.
520 : *
521 : * A re-check after the optimizer call should reset the token
522 : * to assignment.
523 : */
524 : void
525 65499866 : typeChecker(Module scope, MalBlkPtr mb, InstrPtr p, int idx, int silent)
526 : {
527 65499866 : int s1 = -1, i, k;
528 65499866 : Module m = 0;
529 :
530 65499866 : p->typechk = TYPE_UNKNOWN;
531 65499866 : if ((p->fcn || p->blk) && p->token >= FCNcall && p->token <= PATcall) {
532 42721270 : p->token = ASSIGNsymbol;
533 42721270 : p->fcn = NULL;
534 42721270 : p->blk = NULL;
535 : }
536 :
537 65499866 : if (isaSignature(p)) {
538 4199050 : for (k = 0; k < p->argc; k++)
539 2104183 : setVarFixed(mb, getArg(p, k));
540 2097962 : for (k = p->retc; k < p->argc; k++) {
541 3095 : prepostProcess(getArgType(mb, p, k), p, k, mb);
542 : }
543 2094867 : p->typechk = TYPE_RESOLVED;
544 4195865 : for (k = 0; k < p->retc; k++)
545 2627774 : p->typechk = MIN(p->typechk, typeKind(mb, p, 0));
546 56653621 : return;
547 : }
548 63404999 : if (getFunctionId(p) && getModuleId(p)) {
549 54560080 : m = findModule(scope, getModuleId(p));
550 54559318 : s1 = findFunctionType(m, mb, p, idx, silent);
551 :
552 54558841 : if (s1 >= 0)
553 : return;
554 : /*
555 : * Could not find a function that statisfies the constraints.
556 : * If the instruction is just a function header we may
557 : * continue. Likewise, the function and module may refer to
558 : * string variables known only at runtime.
559 : *
560 : * In all other cases we should generate a message, but only
561 : * if we know that the error was not caused by checking the
562 : * definition of a polymorphic function or the module or
563 : * function name are variables, In those cases, the detailed
564 : * analysis is performed upon an actual call.
565 : */
566 1080 : if (!isaSignature(p) && !getInstrPtr(mb, 0)->polymorphic) {
567 1068 : if (!silent) {
568 23 : char *errsig = NULL;
569 23 : if (!malLibraryEnabled(p->modname)) {
570 0 : mb->errors = createMalException(mb, idx, TYPE,
571 : "'%s%s%s' library error in: %s",
572 : (getModuleId(p) ?
573 : getModuleId(p) : ""),
574 0 : (getModuleId(p) ? "." : ""),
575 : getFunctionId(p),
576 : malLibraryHowToEnable(p->
577 : modname));
578 : } else {
579 23 : bool free_errsig = false, special_undefined = false;
580 23 : errsig = malLibraryHowToEnable(p->modname);
581 23 : if (!strcmp(errsig, "")) {
582 23 : errsig = instruction2str(mb, 0, p,
583 : (LIST_MAL_NAME | LIST_MAL_TYPE
584 : | LIST_MAL_VALUE));
585 23 : free_errsig = true;
586 : } else {
587 : special_undefined = true;
588 : }
589 69 : mb->errors = createMalException(mb, idx, TYPE,
590 : "'%s%s%s' undefined%s: %s",
591 : (getModuleId(p) ?
592 : getModuleId(p) : ""),
593 23 : (getModuleId(p) ? "." : ""),
594 : getFunctionId(p),
595 : special_undefined ? "" :
596 : " in",
597 : errsig ? errsig :
598 : "failed instruction2str()");
599 23 : if (free_errsig)
600 23 : GDKfree(errsig);
601 : }
602 : }
603 1068 : p->typechk = TYPE_UNKNOWN;
604 : } else
605 12 : p->typechk = TYPE_RESOLVED;
606 1080 : return;
607 : }
608 : /*
609 : * When we arrive here the operator is an assignment.
610 : * The language should also recognize (a,b):=(1,2);
611 : * This is achieved by propagation of the rhs types to the lhs
612 : * variables.
613 : */
614 8844919 : if (getFunctionId(p)) {
615 : return;
616 : }
617 8845011 : if (p->retc >= 1 && p->argc > p->retc && p->argc != 2 * p->retc) {
618 7 : if (!silent) {
619 7 : mb->errors = createMalException(mb, idx, TYPE,
620 : "Multiple assignment mismatch");
621 : }
622 7 : p->typechk = TYPE_RESOLVED;
623 : } else
624 8845004 : p->typechk = TYPE_RESOLVED;
625 16115561 : for (k = 0, i = p->retc; k < p->retc && i < p->argc; i++, k++) {
626 7270342 : int rhs = getArgType(mb, p, i);
627 7270342 : int lhs = getArgType(mb, p, k);
628 :
629 7270342 : if (rhs != TYPE_void) {
630 7270177 : if (resolveType(&s1, lhs, rhs) < 0) {
631 5 : typeMismatch(mb, p, idx, lhs, rhs, silent);
632 5 : return;
633 : }
634 : } else {
635 : /*
636 : * The language permits assignment of 'nil' to any variable,
637 : * using the target type.
638 : */
639 165 : if (lhs != TYPE_void && lhs != TYPE_any) {
640 0 : ValRecord cst;
641 0 : int k;
642 :
643 0 : cst.vtype = TYPE_void;
644 0 : cst.val.oval = void_nil;
645 0 : cst.len = 0;
646 :
647 0 : rhs = isaBatType(lhs) ? TYPE_bat : lhs;
648 0 : k = defConstant(mb, rhs, &cst);
649 3 : if (k >= 0)
650 3 : p->argv[i] = k;
651 3 : rhs = lhs;
652 : }
653 : }
654 :
655 7270550 : if (!isVarFixed(mb, getArg(p, k))) {
656 3202189 : setVarType(mb, getArg(p, k), rhs);
657 3202189 : setVarFixed(mb, getArg(p, k));
658 : }
659 7270550 : prepostProcess(s1, p, i, mb);
660 7270550 : prepostProcess(s1, p, k, mb);
661 : }
662 : /* the case where we have no rhs */
663 8845219 : if (p->barrier && p->retc == p->argc)
664 487324 : for (k = 0; k < p->retc; k++) {
665 244197 : int tpe = getArgType(mb, p, k);
666 244197 : if (isaBatType(tpe) ||
667 241777 : ATOMtype(tpe) == TYPE_str ||
668 241777 : (!isPolyType(tpe) && tpe < MAXATOMS && ATOMextern(tpe)))
669 2426 : setVarCleanup(mb, getArg(p, k));
670 : }
671 : }
672 :
673 : /*
674 : * After the parser finishes, we have to look for semantic errors,
675 : * such as flow of control problems and possible typeing conflicts.
676 : * The nesting of BARRIER and CATCH statements with their associated
677 : * flow of control primitives LEAVE and RETRY should form a valid
678 : * hierarchy. Failure to comply is considered a structural error
679 : * and leads to flagging the function as erroneous.
680 : * Also check general conformaty of the ML block structure.
681 : * It should start with a signature and finish with and ENDsymbol
682 : *
683 : * Type checking a program is limited to those instructions that are
684 : * not resolved yet. Once the program is completely checked, further calls
685 : * should be ignored. This should be separately administered for the flow
686 : * as well, because a dynamically typed instruction should later on not
687 : * lead to a re-check when it was already fully analyzed.
688 : */
689 : str
690 2850414 : chkTypes(Module s, MalBlkPtr mb, int silent)
691 : {
692 2850414 : InstrPtr p = 0;
693 2850414 : int i;
694 2850414 : str msg = MAL_SUCCEED;
695 :
696 157765421 : for (i = 0; mb->errors == NULL && i < mb->stop; i++) {
697 154915274 : p = getInstrPtr(mb, i);
698 154915274 : assert(p != NULL);
699 154915274 : if (p->typechk != TYPE_RESOLVED)
700 64580756 : typeChecker(s, mb, p, i, silent);
701 : }
702 2850147 : if (mb->errors) {
703 35 : msg = mb->errors;
704 35 : mb->errors = NULL;
705 : }
706 2850147 : return msg;
707 : }
708 :
709 : /*
710 : * Type checking an individual instruction is dangerous,
711 : * because it ignores data flow and variable declarations.
712 : */
713 : int
714 11 : chkInstruction(Module s, MalBlkPtr mb, InstrPtr p)
715 : {
716 11 : if (mb->errors == MAL_SUCCEED) {
717 11 : p->typechk = TYPE_UNKNOWN;
718 11 : typeChecker(s, mb, p, getPC(mb, p), TRUE);
719 : }
720 11 : return mb->errors != MAL_SUCCEED;
721 : }
722 :
723 : /*
724 : * Perform silent check on the program, merely setting the error flag.
725 : */
726 : str
727 548348 : chkProgram(Module s, MalBlkPtr mb)
728 : {
729 548348 : str msg;
730 : /* it is not ready yet, too fragile
731 : mb->typefixed = mb->stop == chk; ignored END */
732 : /* if( mb->flowfixed == 0)*/
733 :
734 548348 : if (mb->errors) {
735 23 : msg = mb->errors;
736 23 : mb->errors = NULL;
737 23 : return msg;
738 : }
739 548325 : msg = chkTypes(s, mb, FALSE);
740 548337 : if (msg == MAL_SUCCEED)
741 548302 : msg = chkFlow(mb);
742 548302 : if (msg == MAL_SUCCEED)
743 548290 : msg = chkDeclarations(mb);
744 : return msg;
745 : }
746 :
747 : /*
748 : * Polymorphic type analysis
749 : * MAL provides for type variables of the form any$N. This feature
750 : * supports polymorphic types, but also complicates the subsequent
751 : * analysis. A variable typed with any$N not occuring in the function
752 : * header leads to a dynamic typed statement. In principle we have
753 : * to type check the function upon each call.
754 : */
755 : static int
756 2627774 : typeKind(MalBlkPtr mb, InstrPtr p, int i)
757 : {
758 2627774 : malType t = getArgType(mb, p, i);
759 2627774 : if (t == TYPE_any || isAnyExpression(t)) {
760 1053529 : return TYPE_UNKNOWN;
761 : }
762 : return TYPE_RESOLVED;
763 : }
764 :
765 : /*
766 : * For a polymorphic commands we do not generate a cloned version.
767 : * It suffices to determine the actual return value taking into
768 : * account the type variable constraints.
769 : */
770 : static malType
771 128792732 : getPolyType(malType t, int *polytype)
772 : {
773 128792732 : int ti;
774 128792732 : int tail;
775 :
776 128792732 : ti = getTypeIndex(t);
777 128792732 : if (!isaBatType(t) && ti > 0)
778 13762278 : return polytype[ti];
779 :
780 115030454 : tail = ti == 0 ? getBatType(t) : polytype[ti];
781 115030454 : if (isaBatType(t)) {
782 108236273 : tail = newBatType(tail);
783 : }
784 : return tail;
785 : }
786 :
787 : /*
788 : * Each argument is checked for binding of polymorphic arguments.
789 : * This routine assumes that the type index is indeed smaller than maxarg.
790 : * (The parser currently enforces a single digit from 1-9 )
791 : * The polymorphic type 'any', i.e. any_0, does never constraint an operation
792 : * it can match with all polymorphic types.
793 : * The routine returns the instanciated formal type for subsequent
794 : * type resolution.
795 : */
796 : static int
797 94907693 : updateTypeMap(int formal, int actual, int polytype[MAXTYPEVAR])
798 : {
799 94907693 : int h, t, ret = 0;
800 :
801 94907693 : if (formal == TYPE_bat && isaBatType(actual))
802 : return 0;
803 :
804 94907693 : if ((h = getTypeIndex(formal))) {
805 42817240 : if (isaBatType(actual) && !isaBatType(formal) &&
806 3811447 : (polytype[h] == TYPE_any || polytype[h] == actual)) {
807 2875582 : polytype[h] = actual;
808 2875582 : ret = 0;
809 2875582 : goto updLabel;
810 : }
811 39941658 : t = getBatType(actual);
812 39941658 : if (t != polytype[h]) {
813 24045366 : if (polytype[h] == TYPE_bat && isaBatType(actual))
814 : ret = 0;
815 24045366 : else if (polytype[h] == TYPE_any)
816 23540845 : polytype[h] = t;
817 : else {
818 504521 : ret = -1;
819 504521 : goto updLabel;
820 : }
821 : }
822 : }
823 91527590 : if (isaBatType(formal)) {
824 78037045 : if (!isaBatType(actual) && actual != TYPE_bat)
825 : return -1;
826 : }
827 15365983 : updLabel:
828 : return ret;
829 : }
|