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