LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - language.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 89 43.8 %
Date: 2021-01-13 20:07:21 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       46412 : MALstartDataflow( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     150             : {
     151       46412 :         bit *ret = getArgReference_bit(stk,pci,0);
     152       46412 :         int pc = getPC(mb,pci);
     153             : 
     154       46412 :         if ( pc <0 || pc > pci->jump)
     155           0 :                 throw(MAL,"language.dataflow","Illegal statement range");
     156       46412 :         *ret = 0;       /* continue at end of block */
     157       46412 :         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     1308480 : MALpass( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     176             : {
     177             :         (void) cntxt;
     178             :         (void) mb;
     179             :         (void) stk;
     180             :         (void) pci;
     181     1308480 :         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, fcnName, modName, ahelp;
     194             : 
     195           1 :         msg= compileString(&sym, cntxt,*code);
     196           1 :         if( msg == MAL_SUCCEED) {
     197             :                 assert(cntxt->usermodule);
     198             :                 //mnstr_printf(cntxt->fdout,"#register FUNCTION %s.%s\n",
     199             :                         //getModuleId(sym->def->stmt[0]), getFunctionId(sym->def->stmt[0]));
     200           1 :                 mb= sym->def;
     201           1 :                 fcnName = putName(*fcn);
     202           1 :                 modName = putName(*mod);
     203           1 :                 ahelp = GDKstrdup(*help);
     204           1 :                 if(fcnName == NULL || modName == NULL || ahelp == NULL) {
     205           0 :                         freeSymbol(sym);
     206           0 :                         GDKfree(ahelp);
     207           0 :                         throw(MAL, "language.register", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     208             :                 }
     209           1 :                 mb->help= ahelp;
     210           1 :                 sig= getSignature(sym);
     211           1 :                 sym->name= fcnName;
     212           1 :                 setModuleId(sig, modName);
     213           1 :                 setFunctionId(sig, sym->name);
     214           1 :                 insertSymbol(findModule(cntxt->usermodule, getModuleId(sig)), sym);
     215             :         }
     216             :         return msg;
     217             : }
     218             : static str
     219           0 : CMDevalFile(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     220             : {
     221           0 :         str s = *getArgReference_str(stk,pci,1);
     222             :         char *msg = NULL;
     223             :         (void) mb;
     224             :         (void) cntxt;
     225             : 
     226           0 :         if (s == 0)
     227           0 :                 throw(MAL, "mal.evalFile", RUNTIME_FILE_NOT_FOUND "missing file name");
     228             : 
     229           0 :         if (!MT_path_absolute(s)) {
     230           0 :                 char *buf = GDKmalloc(strlen(monet_cwd) + strlen(s) + 2);
     231           0 :                 if ( buf == NULL)
     232           0 :                         throw(MAL,"language.eval", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     233             : 
     234           0 :                 stpcpy(stpcpy(stpcpy(buf, monet_cwd), DIR_SEP_STR), s);
     235           0 :                 msg = evalFile(buf, 0);
     236           0 :                 GDKfree(buf);
     237             :         } else
     238           0 :                 msg = evalFile(s, 0);
     239             :         return msg;
     240             : }
     241             : /*
     242             :  * Calling a BAT is simply translated into a concatenation of
     243             :  * all the unquoted strings and then passing it to the callEval.
     244             :  */
     245             : static str
     246           0 : CMDcallBAT(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     247             : {
     248             :         (void) cntxt;
     249             :         (void) mb;
     250             :         (void) stk;
     251             :         (void) pci;             /* fool compiler */
     252           0 :         throw(MAL, "mal.call", SQLSTATE(0A000) PROGRAM_NYI);
     253             : }
     254             : 
     255             : #include "mel.h"
     256             : mel_func language_init_funcs[] = {
     257             :  pattern("language", "call", CMDcallString, false, "Evaluate a MAL string program.", args(1,2, arg("",void),arg("s",str))),
     258             :  pattern("language", "call", CMDcallFunction, false, "", args(1,3, arg("",void),arg("m",str),arg("f",str))),
     259             :  pattern("language", "call", CMDcallBAT, false, "Evaluate a program stored in a BAT.", args(1,2, arg("",void),batarg("s",str))),
     260             :  pattern("language", "source", CMDevalFile, false, "Merge the instructions stored in the file with the current program.", args(1,2, arg("",void),arg("f",str))),
     261             :  command("language", "raise", CMDraise, true, "Raise an exception labeled \nwith a specific message.", args(1,2, arg("",str),arg("msg",str))),
     262             :  command("language", "assert", MALassertBit, true, "", args(1,3, arg("",void),arg("v",bit),arg("term",str))),
     263             :  command("language", "assert", MALassertSht, true, "", args(1,3, arg("",void),arg("v",sht),arg("term",str))),
     264             :  command("language", "assert", MALassertInt, true, "", args(1,3, arg("",void),arg("v",int),arg("term",str))),
     265             :  command("language", "assert", MALassertLng, true, "", args(1,3, arg("",void),arg("v",lng),arg("term",str))),
     266             :  command("language", "assert", MALassertStr, true, "", args(1,3, arg("",void),arg("v",str),arg("term",str))),
     267             :  command("language", "assert", MALassertOid, true, "", args(1,3, arg("",void),arg("v",oid),arg("term",str))),
     268             :  pattern("language", "assert", MALassertTriple, true, "Assertion test.", args(1,5, arg("",void),argany("v",1),arg("pname",str),arg("oper",str),argany("val",2))),
     269             :  pattern("language", "dataflow", MALstartDataflow, false, "The current guarded block is executed using dataflow control. ", args(1,1, arg("",bit))),
     270             :  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))),
     271             :  pattern("language", "pass", MALpass, false, "Cheap instruction to disgard storage while retaining the dataflow dependency", args(0,1, argany("v",1))),
     272             :  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))),
     273             :  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))),
     274             : #ifdef HAVE_HGE
     275             :  command("language", "assert", MALassertHge, true, "", args(0,2, arg("v",hge),arg("term",str))),
     276             : #endif
     277             :  { .imp=NULL }
     278             : };
     279             : #include "mal_import.h"
     280             : #ifdef _MSC_VER
     281             : #undef read
     282             : #pragma section(".CRT$XCU",read)
     283             : #endif
     284         255 : LIB_STARTUP_FUNC(init_language_mal)
     285         255 : { mal_module("language", NULL, language_init_funcs); }

Generated by: LCOV version 1.14