| 1 | /* | 
|---|
| 2 | * This Source Code Form is subject to the terms of the Mozilla Public | 
|---|
| 3 | * License, v. 2.0.  If a copy of the MPL was not distributed with this | 
|---|
| 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. | 
|---|
| 5 | * | 
|---|
| 6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. | 
|---|
| 7 | */ | 
|---|
| 8 |  | 
|---|
| 9 | /* | 
|---|
| 10 | * @f run_adder | 
|---|
| 11 | * @a The ROX Team | 
|---|
| 12 | * @+ Dynamic Statement Generation Example | 
|---|
| 13 | * | 
|---|
| 14 | * we have a function: adder.generate(target, batch) | 
|---|
| 15 | * that is recognized by this scheduler. | 
|---|
| 16 | * @example | 
|---|
| 17 | *         x := 0; | 
|---|
| 18 | * 	x := adder.generate(10,2) | 
|---|
| 19 | * 	io.print(x); | 
|---|
| 20 | * @end example | 
|---|
| 21 | * should produce on first iteration | 
|---|
| 22 | * @example | 
|---|
| 23 | * 	x := 0; | 
|---|
| 24 | * 	x := calc.+(x,1); | 
|---|
| 25 | * 	x := calc.+(x,1); | 
|---|
| 26 | * 	x := adder.generate(8,2) | 
|---|
| 27 | * 	io.print(x); | 
|---|
| 28 | * @end example | 
|---|
| 29 | * next when generate() is found: | 
|---|
| 30 | * @example | 
|---|
| 31 | * 	x := calc.+(x,1); | 
|---|
| 32 | * 	x := calc.+(x,1); | 
|---|
| 33 | * 	x := adder.generate(6,2) | 
|---|
| 34 | * 	io.print(x); | 
|---|
| 35 | * @end example | 
|---|
| 36 | * etc, until x = base | 
|---|
| 37 | * | 
|---|
| 38 | */ | 
|---|
| 39 | /* | 
|---|
| 40 | * @+ Adder implementation | 
|---|
| 41 | * The code below is a mixture of generic routines and | 
|---|
| 42 | * sample implementations to run the tests. | 
|---|
| 43 | */ | 
|---|
| 44 | #include "monetdb_config.h" | 
|---|
| 45 | #include "mal_builder.h" | 
|---|
| 46 | #include "opt_prelude.h" | 
|---|
| 47 | #include "run_adder.h" | 
|---|
| 48 |  | 
|---|
| 49 | /* | 
|---|
| 50 | * @- | 
|---|
| 51 | * THe choice operator first searches the next one to identify | 
|---|
| 52 | * the fragment to be optimized and to gain access to the variables | 
|---|
| 53 | * without the need to declare them upfront. | 
|---|
| 54 | */ | 
|---|
| 55 | /* helper routine that at runtime propagates values to the stack */ | 
|---|
| 56 | static void adder_addval(MalBlkPtr mb, MalStkPtr stk, int i) { | 
|---|
| 57 | ValPtr rhs, lhs = &stk->stk[i]; | 
|---|
| 58 | if (isVarConstant(mb,i) > 0 ){ | 
|---|
| 59 | rhs = &getVarConstant(mb,i); | 
|---|
| 60 | VALcopy(lhs,rhs); | 
|---|
| 61 | } else { | 
|---|
| 62 | lhs->vtype = getVarGDKType(mb,i); | 
|---|
| 63 | lhs->val.pval = 0; | 
|---|
| 64 | lhs->len = 0; | 
|---|
| 65 | } | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | str | 
|---|
| 69 | RUNadder(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) | 
|---|
| 70 | { | 
|---|
| 71 | int total; | 
|---|
| 72 | int batch; | 
|---|
| 73 | int size; | 
|---|
| 74 | int i,pc; | 
|---|
| 75 | InstrPtr q, *old; | 
|---|
| 76 | int oldtop; | 
|---|
| 77 |  | 
|---|
| 78 | (void) cntxt; | 
|---|
| 79 | pc = getPC(mb,p); | 
|---|
| 80 | total = *getArgReference_int(stk,p,1); | 
|---|
| 81 | batch = *getArgReference_int(stk,p,2); | 
|---|
| 82 | if (total == 0) return MAL_SUCCEED; | 
|---|
| 83 |  | 
|---|
| 84 | old = mb->stmt; | 
|---|
| 85 | oldtop= mb->stop; | 
|---|
| 86 | size = ((mb->stop+batch) < mb->ssize)? mb->ssize:(mb->stop+batch); | 
|---|
| 87 | mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr)); | 
|---|
| 88 | if (mb->stmt == NULL) { | 
|---|
| 89 | mb->stmt = old; | 
|---|
| 90 | throw(MAL, "adder.generate", SQLSTATE(HY001) MAL_MALLOC_FAIL); | 
|---|
| 91 | } | 
|---|
| 92 | mb->ssize = size; | 
|---|
| 93 | memcpy( mb->stmt, old, sizeof(InstrPtr)*(pc+1)); | 
|---|
| 94 | mb->stop = pc+1; | 
|---|
| 95 |  | 
|---|
| 96 | if (batch > total) total = batch; | 
|---|
| 97 | for (i=0; i<batch; i++) { | 
|---|
| 98 | /* tmp := calc.+(x,1) */ | 
|---|
| 99 | q = newStmt(mb, calcRef, plusRef); | 
|---|
| 100 | getArg(q,0) = getArg(p,0); | 
|---|
| 101 | q = pushArgument(mb, q, getArg(p, 0)); | 
|---|
| 102 | q = pushInt(mb, q, 1); | 
|---|
| 103 | adder_addval(mb, stk, getArg(q,2)); | 
|---|
| 104 | } | 
|---|
| 105 | total -= batch; | 
|---|
| 106 | *getArgReference_int(stk,p,1) = total; | 
|---|
| 107 | getVar(mb,getArg(p,1))->value.val.ival = total; /* also set in symbol table */ | 
|---|
| 108 | if (total > 0) { | 
|---|
| 109 | if ((q = copyInstruction(p)) == NULL) { | 
|---|
| 110 | for(i=0; i<mb->stop; i++) | 
|---|
| 111 | if( mb->stmt[i]) | 
|---|
| 112 | freeInstruction(mb->stmt[i]); | 
|---|
| 113 | GDKfree(mb->stmt); | 
|---|
| 114 | mb->stmt = old; | 
|---|
| 115 | throw(MAL, "adder.generate", SQLSTATE(HY001) MAL_MALLOC_FAIL); | 
|---|
| 116 | } | 
|---|
| 117 | pushInstruction(mb, q); | 
|---|
| 118 | } | 
|---|
| 119 | memcpy(mb->stmt+mb->stop, old+pc+1, sizeof(InstrPtr) * (oldtop-pc)-1); | 
|---|
| 120 | mb->stop += (oldtop-pc)-1; | 
|---|
| 121 |  | 
|---|
| 122 | /* check new statments for sanity */ | 
|---|
| 123 | chkTypes(cntxt->usermodule, mb, FALSE); | 
|---|
| 124 | chkFlow(mb); | 
|---|
| 125 | chkDeclarations(mb); | 
|---|
| 126 |  | 
|---|
| 127 | GDKfree(old); | 
|---|
| 128 | return MAL_SUCCEED; | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|