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