LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_resolve.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 241 248 97.2 %
Date: 2021-09-14 22:17:06 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.14