LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - language.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 40 90 44.4 %
Date: 2021-10-27 03:06:47 Functions: 6 18 33.3 %

          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             :  *  Martin Kersten
      11             :  * Language Extensions
      12             :  * Iterators over scalar ranges are often needed, also at the MAL level.
      13             :  * The barrier and control primitives are sufficient to mimic them directly.
      14             :  *
      15             :  * The modules located in the kernel directory should not
      16             :  * rely on the MAL datastructures. That's why we have to deal with
      17             :  * some bat operations here and delegate the signature to the
      18             :  * proper module upon loading.
      19             :  *
      20             :  * Running a script is typically used to initialize a context.
      21             :  * Therefore we need access to the runtime context.
      22             :  * For the call variants we have
      23             :  * to determine an easy way to exchange the parameter/return values.
      24             :  */
      25             : 
      26             : #include "monetdb_config.h"
      27             : #include "mal.h"
      28             : #include "mal_module.h"
      29             : #include "mal_session.h"
      30             : #include "mal_resolve.h"
      31             : #include "mal_client.h"
      32             : #include "mal_interpreter.h"
      33             : #include "mal_dataflow.h"
      34             : 
      35             : static str
      36           0 : CMDraise(str *ret, str *msg)
      37             : {
      38             :         str res;
      39           0 :         *ret = GDKstrdup(*msg);
      40           0 :         if( *ret == NULL)
      41           0 :                 throw(MAL, "mal.raise", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      42           0 :         res = GDKstrdup(*msg);
      43           0 :         if( res == NULL)
      44           0 :                 throw(MAL, "mal.raise", SQLSTATE(HY013) MAL_MALLOC_FAIL);
      45             :         return res;
      46             : }
      47             : 
      48             : static str
      49           0 : MALassertBit(void *ret, bit *val, str *msg){
      50             :         (void) ret;
      51           0 :         if( *val == 0 || is_bit_nil(*val))
      52           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      53             :         return MAL_SUCCEED;
      54             : }
      55             : static str
      56           0 : MALassertInt(void *ret, int *val, str *msg){
      57             :         (void) ret;
      58           0 :         if( *val == 0 || is_int_nil(*val))
      59           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      60             :         return MAL_SUCCEED;
      61             : }
      62             : static str
      63           0 : MALassertLng(void *ret, lng *val, str *msg){
      64             :         (void) ret;
      65           0 :         if( *val == 0 || is_lng_nil(*val))
      66           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      67             :         return MAL_SUCCEED;
      68             : }
      69             : #ifdef HAVE_HGE
      70             : static str
      71           0 : MALassertHge(void *ret, hge *val, str *msg){
      72             :         (void) ret;
      73           0 :         if( *val == 0 || is_hge_nil(*val))
      74           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      75             :         return MAL_SUCCEED;
      76             : }
      77             : #endif
      78             : static str
      79           0 : MALassertSht(void *ret, sht *val, str *msg){
      80             :         (void) ret;
      81           0 :         if( *val == 0 || is_sht_nil(*val))
      82           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      83             :         return MAL_SUCCEED;
      84             : }
      85             : static str
      86           0 : MALassertOid(void *ret, oid *val, str *msg){
      87             :         (void) ret;
      88           0 :         if( is_oid_nil(*val))
      89           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      90             :         return MAL_SUCCEED;
      91             : }
      92             : static str
      93           0 : MALassertStr(void *ret, str *val, str *msg){
      94             :         (void) ret;
      95           0 :         if( *val == str_nil)
      96           0 :                 throw(MAL, "mal.assert", "%s", *msg);
      97             :         return MAL_SUCCEED;
      98             : }
      99             : 
     100             : static str
     101           0 : MALassertTriple(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){
     102             :         (void) cntxt;
     103             :         (void) mb;
     104             :         (void) stk;
     105             :         (void) p;
     106           0 :         throw(MAL, "mal.assert", SQLSTATE(0A000) PROGRAM_NYI);
     107             : }
     108             : 
     109             : /*
     110             :  * Printing
     111             :  * The print commands are implemented as single instruction rules,
     112             :  * because they need access to the calling context.
     113             :  * At a later stage we can look into the issues related to
     114             :  * parsing the format string as part of the initialization phase.
     115             :  * The old method in V4 essentially causes a lot of overhead
     116             :  * because you have to prepare for the worst (e.g. mismatch format
     117             :  * identifier and argument value)
     118             :  *
     119             :  * Input redirectionrs
     120             :  */
     121             : static str
     122           8 : CMDcallString(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     123             : {
     124             :         str *s;
     125             : 
     126             :         (void) mb;              /* fool compiler */
     127           8 :         s = getArgReference_str(stk, pci, 1);
     128           8 :         if (strlen(*s) == 0)
     129             :                 return MAL_SUCCEED;
     130           8 :         return callString(cntxt, *s, FALSE);
     131             : }
     132             : 
     133             : static str
     134           2 : CMDcallFunction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     135             : {
     136           2 :         str mod = *getArgReference_str(stk,pci,1);
     137           2 :         str fcn = *getArgReference_str(stk,pci,2);
     138             :         char buf[BUFSIZ];
     139             : 
     140             :         (void) mb;              /* fool compiler */
     141           2 :         if (strlen(mod) == 0 || strlen(fcn) ==0)
     142             :                 return MAL_SUCCEED;
     143             :         // lazy implementation of the call
     144           2 :         snprintf(buf,BUFSIZ,"%s.%s();",mod,fcn);
     145           2 :         return callString(cntxt, buf, FALSE);
     146             : }
     147             : 
     148             : static str
     149      123562 : MALstartDataflow( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     150             : {
     151      123562 :         bit *ret = getArgReference_bit(stk,pci,0);
     152      123562 :         int pc = getPC(mb,pci);
     153             : 
     154      123562 :         if ( pc <0 || pc > pci->jump)
     155           0 :                 throw(MAL,"language.dataflow","Illegal statement range");
     156      123562 :         *ret = 0;       /* continue at end of block */
     157      123562 :         return runMALdataflow(cntxt, mb, pc, pci->jump, stk);
     158             : }
     159             : 
     160             : /*
     161             :  * Garbage collection over variables can be postponed by grouping
     162             :  * all dependent ones in a single sink() instruction.
     163             :  */
     164             : static str
     165           0 : MALgarbagesink( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     166             : {
     167             :         (void) cntxt;
     168             :         (void) mb;
     169             :         (void) stk;
     170             :         (void) pci;
     171           0 :         return MAL_SUCCEED;
     172             : }
     173             : 
     174             : static str
     175     1758512 : MALpass( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     176             : {
     177             :         (void) cntxt;
     178             :         (void) mb;
     179             :         (void) stk;
     180             :         (void) pci;
     181     1758512 :         return MAL_SUCCEED;
     182             : }
     183             : 
     184             : static str
     185           1 : CMDregisterFunction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     186             : {
     187           1 :         Symbol sym= NULL;
     188           1 :         str *mod = getArgReference_str(stk,pci,1);
     189           1 :         str *fcn = getArgReference_str(stk,pci,2);
     190           1 :         str *code = getArgReference_str(stk,pci,3);
     191           1 :         str *help = getArgReference_str(stk,pci,4);
     192             :         InstrPtr sig;
     193             :         str msg, ahelp;
     194             :         const char *fcnName, *modName;
     195             : 
     196           1 :         msg= compileString(&sym, cntxt,*code);
     197           1 :         if( msg == MAL_SUCCEED) {
     198           1 :                 assert(cntxt->usermodule);
     199             :                 //mnstr_printf(cntxt->fdout,"#register FUNCTION %s.%s\n",
     200             :                         //getModuleId(sym->def->stmt[0]), getFunctionId(sym->def->stmt[0]));
     201           1 :                 mb= sym->def;
     202           1 :                 fcnName = putName(*fcn);
     203           1 :                 modName = putName(*mod);
     204           1 :                 ahelp = GDKstrdup(*help);
     205           1 :                 if(fcnName == NULL || modName == NULL || ahelp == NULL) {
     206           0 :                         freeSymbol(sym);
     207           0 :                         GDKfree(ahelp);
     208           0 :                         throw(MAL, "language.register", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     209             :                 }
     210           1 :                 mb->help= ahelp;
     211           1 :                 sig= getSignature(sym);
     212           1 :                 sym->name= fcnName;
     213           1 :                 setModuleId(sig, modName);
     214           1 :                 setFunctionId(sig, sym->name);
     215           1 :                 insertSymbol(findModule(cntxt->usermodule, getModuleId(sig)), sym);
     216             :         }
     217             :         return msg;
     218             : }
     219             : static str
     220           0 : CMDevalFile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     221             : {
     222           0 :         str s = *getArgReference_str(stk,pci,1);
     223             :         char *msg = NULL;
     224             :         (void) mb;
     225             :         (void) cntxt;
     226             : 
     227           0 :         if (s == 0)
     228           0 :                 throw(MAL, "mal.evalFile", RUNTIME_FILE_NOT_FOUND "missing file name");
     229             : 
     230           0 :         if (!MT_path_absolute(s)) {
     231           0 :                 char *buf = GDKmalloc(strlen(monet_cwd) + strlen(s) + 2);
     232           0 :                 if ( buf == NULL)
     233           0 :                         throw(MAL,"language.eval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     234             : 
     235           0 :                 stpcpy(stpcpy(stpcpy(buf, monet_cwd), DIR_SEP_STR), s);
     236           0 :                 msg = evalFile(buf, 0);
     237           0 :                 GDKfree(buf);
     238             :         } else
     239           0 :                 msg = evalFile(s, 0);
     240             :         return msg;
     241             : }
     242             : /*
     243             :  * Calling a BAT is simply translated into a concatenation of
     244             :  * all the unquoted strings and then passing it to the callEval.
     245             :  */
     246             : static str
     247           0 : CMDcallBAT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     248             : {
     249             :         (void) cntxt;
     250             :         (void) mb;
     251             :         (void) stk;
     252             :         (void) pci;             /* fool compiler */
     253           0 :         throw(MAL, "mal.call", SQLSTATE(0A000) PROGRAM_NYI);
     254             : }
     255             : 
     256             : #include "mel.h"
     257             : mel_func language_init_funcs[] = {
     258             :  pattern("language", "call", CMDcallString, false, "Evaluate a MAL string program.", args(1,2, arg("",void),arg("s",str))),
     259             :  pattern("language", "call", CMDcallFunction, false, "", args(1,3, arg("",void),arg("m",str),arg("f",str))),
     260             :  pattern("language", "call", CMDcallBAT, false, "Evaluate a program stored in a BAT.", args(1,2, arg("",void),batarg("s",str))),
     261             :  pattern("language", "source", CMDevalFile, false, "Merge the instructions stored in the file with the current program.", args(1,2, arg("",void),arg("f",str))),
     262             :  command("language", "raise", CMDraise, true, "Raise an exception labeled \nwith a specific message.", args(1,2, arg("",str),arg("msg",str))),
     263             :  command("language", "assert", MALassertBit, true, "", args(1,3, arg("",void),arg("v",bit),arg("term",str))),
     264             :  command("language", "assert", MALassertSht, true, "", args(1,3, arg("",void),arg("v",sht),arg("term",str))),
     265             :  command("language", "assert", MALassertInt, true, "", args(1,3, arg("",void),arg("v",int),arg("term",str))),
     266             :  command("language", "assert", MALassertLng, true, "", args(1,3, arg("",void),arg("v",lng),arg("term",str))),
     267             :  command("language", "assert", MALassertStr, true, "", args(1,3, arg("",void),arg("v",str),arg("term",str))),
     268             :  command("language", "assert", MALassertOid, true, "", args(1,3, arg("",void),arg("v",oid),arg("term",str))),
     269             :  pattern("language", "assert", MALassertTriple, true, "Assertion test.", args(1,5, arg("",void),argany("v",1),arg("pname",str),arg("oper",str),argany("val",2))),
     270             :  pattern("language", "dataflow", MALstartDataflow, false, "The current guarded block is executed using dataflow control. ", args(1,1, arg("",bit))),
     271             :  pattern("language", "sink", MALgarbagesink, false, "Variables to be considered together when triggering garbage collection.\nUsed in the dataflow blocks to avoid early release of values.", args(1,2, arg("",void),varargany("v",0))),
     272             :  pattern("language", "pass", MALpass, false, "Cheap instruction to disgard storage while retaining the dataflow dependency", args(0,1, argany("v",1))),
     273             :  pattern("language", "block", deblockdataflow, false, "Block on availability of all variables w, and then pass on v", args(1,3, arg("",int),arg("v",int),varargany("w",0))),
     274             :  pattern("language", "register", CMDregisterFunction, false, "Compile the code string to MAL and register it as a function.", args(1,5, arg("",void),arg("m",str),arg("f",str),arg("code",str),arg("help",str))),
     275             : #ifdef HAVE_HGE
     276             :  command("language", "assert", MALassertHge, true, "", args(0,2, arg("v",hge),arg("term",str))),
     277             : #endif
     278             :  { .imp=NULL }
     279             : };
     280             : #include "mal_import.h"
     281             : #ifdef _MSC_VER
     282             : #undef read
     283             : #pragma section(".CRT$XCU",read)
     284             : #endif
     285         257 : LIB_STARTUP_FUNC(init_language_mal)
     286         257 : { mal_module("language", NULL, language_init_funcs); }

Generated by: LCOV version 1.14