LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_resolve.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 304 326 93.3 %
Date: 2024-04-25 20:03:45 Functions: 10 10 100.0 %

          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             : }

Generated by: LCOV version 1.14