Fixed newline characters throughout the code
[com/gs-lite.git] / src / ftacmp / parse_ext_fcns.h
1 /* ------------------------------------------------
2 Copyright 2014 AT&T Intellectual Property
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7      http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License.
14  ------------------------------------------- */
15 #ifndef __EXT_FCN_DEF_H_INCLUDED__
16 #define __EXT_FCN_DEF_H_INCLUDED__
17
18 #include <string>
19 #include <vector>
20
21 #include "type_objects.h"
22 #include "parse_schema.h"
23
24 class ext_fcn_param{
25 private:
26         std::string type_name;
27         bool handle;
28         bool constant;
29         bool classifier;
30         data_type *dt;
31
32 public:
33         ext_fcn_param(){handle = false; dt=NULL;        };
34         ext_fcn_param(char *t, param_list *plist, int h, int cnst, int clss){
35                 type_name = t;
36                 if(h == 0) handle = false;
37                 else       handle = true;
38                 if(cnst == 1 ) constant = true;
39                 else               constant = false;
40                 if(clss == 1) classifier = true;
41                 else              classifier = false;
42                         
43
44                 dt = new data_type(type_name,plist);
45         };
46
47         data_type *get_dt(){return(dt);};
48
49         bool use_handle(){return handle;};
50         bool is_constant(){return constant;};
51         bool is_classifier(){return classifier;};
52
53 };
54
55
56 class ext_fcn_param_list{
57 private:
58         std::vector<ext_fcn_param *> plist;
59
60 public:
61         ext_fcn_param_list(){};
62         ext_fcn_param_list(ext_fcn_param *val){
63                 plist.push_back(val);
64         };
65
66         ext_fcn_param_list *append(ext_fcn_param *val){
67                 plist.push_back(val);
68                 return(this);
69         };
70
71         int size(){return plist.size();};
72         std::vector<ext_fcn_param *> get_param_list(){return plist;};
73 };
74
75 class ext_fcn_modifier_list{
76 public:
77         std::vector<std::string> modifiers;
78         std::vector<std::string> vals;
79
80         ext_fcn_modifier_list(char *s){
81                 modifiers.push_back(s);
82                 vals.push_back("");
83         };
84
85         ext_fcn_modifier_list(char *s, char *v){
86                 modifiers.push_back(s);
87                 vals.push_back(v);
88         };
89
90         ext_fcn_modifier_list *append(char *s){
91                 modifiers.push_back(s);
92                 vals.push_back("");
93                 return(this);
94         };
95
96         ext_fcn_modifier_list *append(char *s, char *v){
97                 modifiers.push_back(s);
98                 vals.push_back(v);
99                 return(this);
100         };
101 };
102
103 #define EXT_FCN_ 1
104 #define EXT_PRED_ 2
105 #define EXT_AGGR_ 3
106 #define EXT_EXTR_ 4
107 #define EXT_STATE_ 5
108 #define EXT_SFUN_ 6
109
110 class ext_fcn_def{
111 private:
112     int fcn_type;
113         std::string type_name;  // return type name
114         data_type *fdt;                 // return type
115         std::string storage_type_name;  // storage type name
116         data_type *sdt;                                 // storage type
117         std::string fcn_name;   // name for calling this fcn.
118         std::string udaf_name;  // if an extraction function, its udaf.
119         std::string actual_fcn_name;    // if extr. the mapped-to function.
120         std::vector<ext_fcn_param *> ef_param_list;
121         std::vector<std::string> modifiers;     //      keyword modifiers of the fcn
122         std::vector<std::string> vals;          // optional vals of the keywords
123         bool partial;
124 //                      pre-compute these during validation
125         int subaggr_id, superaggr_id, hfta_subaggr_id, hfta_superaggr_id, actual_fcn_id;
126
127 public:
128
129         ext_fcn_def(){
130                 fdt=NULL;
131                 sdt = NULL;
132                 fcn_type=-1;
133         };
134
135         ext_fcn_def(char *t, param_list *p, ext_fcn_modifier_list *m,
136                                 char *f, ext_fcn_param_list *plist){
137                 subaggr_id=superaggr_id=hfta_subaggr_id=hfta_superaggr_id=actual_fcn_id=-1;
138                 if(plist != NULL)
139                         ef_param_list = plist->get_param_list();
140                 if(m != NULL){
141                         modifiers = m->modifiers;
142                         vals = m->vals;
143                 }
144                 type_name = t;
145                 fdt = new data_type(type_name,p);
146                 storage_type_name = "";
147                 sdt = NULL;
148                 udaf_name = "";
149                 actual_fcn_name = "";
150                 fcn_type = EXT_FCN_;
151                 fcn_name = f;
152         };
153
154         ext_fcn_def(ext_fcn_modifier_list *m,
155         char *f, ext_fcn_param_list *plist){
156                 subaggr_id=superaggr_id=hfta_subaggr_id=hfta_superaggr_id=actual_fcn_id=-1;
157                 if(plist != NULL)
158                         ef_param_list = plist->get_param_list();
159                 if(m != NULL){
160                         modifiers = m->modifiers;
161                         vals = m->vals;
162                 }
163                 type_name = "";
164                 fdt = NULL;
165                 storage_type_name = "";
166                 sdt = NULL;
167                 udaf_name = "";
168                 actual_fcn_name = "";
169                 fcn_type = EXT_PRED_;
170                 fcn_name = f;
171         };
172
173         ext_fcn_def(char *t, param_list *p, ext_fcn_modifier_list *m,
174                                 char *f, char *st, ext_fcn_param_list *plist){
175                 subaggr_id=superaggr_id=hfta_subaggr_id=hfta_superaggr_id=actual_fcn_id=-1;
176                 if(plist != NULL)
177                         ef_param_list = plist->get_param_list();
178                 if(m != NULL){
179                         modifiers = m->modifiers;
180                         vals = m->vals;
181                 }
182                 type_name = t;
183                 fdt = new data_type(type_name,p);
184                 storage_type_name = st;
185                 sdt = new data_type(st);
186                 udaf_name = "";
187                 actual_fcn_name = "";
188                 fcn_type = EXT_AGGR_;
189                 fcn_name = f;
190         };
191
192
193         ext_fcn_def(char *t, param_list *p, ext_fcn_modifier_list *m,
194                                 char *f, char *sa, char *af, ext_fcn_param_list *plist){
195                 subaggr_id=superaggr_id=hfta_subaggr_id=hfta_superaggr_id=actual_fcn_id=-1;
196                 if(plist != NULL)
197                         ef_param_list = plist->get_param_list();
198                 if(m != NULL){
199                         modifiers = m->modifiers;
200                         vals = m->vals;
201                 }
202                 type_name = t;
203                 fdt = new data_type(type_name,p);
204                 storage_type_name = "";
205                 sdt = NULL;
206                 udaf_name = sa;
207                 actual_fcn_name = af;
208                 fcn_type = EXT_EXTR_;
209                 fcn_name = f;
210         };
211
212         static ext_fcn_def *make_state_def(char *t, char *n){
213                 ext_fcn_def *retval = new ext_fcn_def();
214                 retval->fcn_type = EXT_STATE_;
215                 retval->storage_type_name = t;
216                 retval->sdt = new data_type(retval->storage_type_name);
217                 retval->fcn_name = n;
218
219                 return retval;
220         }
221
222         static ext_fcn_def *make_sfun_def(char *t, param_list *p,
223                 ext_fcn_modifier_list *m,
224                 char *n, char *s, ext_fcn_param_list *plist){
225                 ext_fcn_def *retval = new ext_fcn_def();
226                 retval->fcn_type = EXT_SFUN_;
227                 retval->type_name = t;
228                 retval->fdt = new data_type(retval->type_name,p);
229                 retval->storage_type_name = s;
230                 retval->fcn_name = n;
231                 if(plist != NULL)
232                         retval->ef_param_list = plist->get_param_list();
233                 if(m != NULL){
234                         retval->modifiers = m->modifiers;
235                         retval->vals= m->vals;
236                 }
237
238                 return retval;
239         }
240
241         data_type *get_fcn_dt(){return(fdt);};
242         data_type *get_storage_dt(){return sdt;};
243         std::string get_storage_state(){return storage_type_name;};
244         std::string get_fcn_name(){return fcn_name;};
245
246         std::vector<data_type *> get_operand_dt(){
247                 int o;
248                 std::vector<data_type *> ret;
249                 for(o=0;o<ef_param_list.size();o++){
250                         ret.push_back(ef_param_list[o]->get_dt());
251                 }
252                 return(ret);
253         };
254         int get_nparams(){return ef_param_list.size();};
255
256         bool is_pred(){return fcn_type == EXT_PRED_;};
257         bool is_fcn(){return fcn_type == EXT_FCN_;};
258         bool is_udaf(){return fcn_type == EXT_AGGR_;};
259         bool is_extr(){return fcn_type == EXT_EXTR_;};
260         bool is_state(){return fcn_type == EXT_STATE_;};
261         bool is_sfun(){return fcn_type == EXT_SFUN_;};
262         int get_fcn_type(){return fcn_type;};
263
264         void set_subaggr_id(int i){subaggr_id = i;};
265         void set_superaggr_id(int i){superaggr_id = i;};
266         void set_hfta_subaggr_id(int i){hfta_subaggr_id = i;};
267         void set_hfta_superaggr_id(int i){hfta_superaggr_id = i;};      
268         void set_actual_fcnid(int i){actual_fcn_id = i;};
269         int get_subaggr_id(){return subaggr_id;};
270         int get_superaggr_id(){return superaggr_id;};
271         int get_hfta_subaggr_id(){return hfta_subaggr_id;};
272         int get_hfta_superaggr_id(){return hfta_superaggr_id;}; 
273         int get_actual_fcn_id(){return actual_fcn_id;};
274
275         std::string get_udaf_name(){return udaf_name;};
276         std::string get_actual_fcn(){return actual_fcn_name;};
277
278
279         bool is_partial(){
280                 int m;
281                 for(m=0;m<modifiers.size();m++){
282                         if(modifiers[m] == "PARTIAL")
283                                 return(true);
284                 }
285                 if(fdt->is_buffer_type()){
286                         return true;
287                 }
288                 return(false);
289         };
290
291         bool is_combinable(){
292                 int m;
293                 for(m=0;m<modifiers.size();m++){
294                         if(modifiers[m] == "COMBINABLE")
295                                 return(true);
296                 }
297                 return(false);
298         };
299
300         bool fta_legal(){
301                 int m;
302                 for(m=0;m<modifiers.size();m++){
303                         if(modifiers[m] == "LFTA_LEGAL" || modifiers[m] == "LFTA_ONLY" || modifiers[m] == "SAMPLING")
304                                 return(true);
305                 }
306                 return(false);
307         };
308
309         bool lfta_only(){
310                 int m;
311                 for(m=0;m<modifiers.size();m++){
312                         if(modifiers[m] == "LFTA_ONLY" || modifiers[m] == "SAMPLING")
313                                 return(true);
314                 }
315                 return(false);
316         };
317
318 //              the SAMPLING modifier and the is_sampling_function
319 //              was aded by Vlad, to support semantic sampling.
320         bool is_sampling_fcn(){
321                 int m;
322                 for(m=0;m<modifiers.size();m++){
323                         if(modifiers[m] == "SAMPLING")
324                                 return(true);
325                 }
326                 return(false);
327         };
328
329 #define COST_FREE 0
330 #define COST_LOW 1
331 #define COST_HIGH 2
332 #define COST_EXPENSIVE 3
333 #define COST_TOP 4
334
335         int get_fcn_cost(){
336                 int m;
337                 for(m=0;m<modifiers.size();m++){
338                         if(modifiers[m] == "COST"){
339                                 if(vals[m] == "FREE")
340                                         return COST_FREE;
341                                 if(vals[m] == "" || vals[m] == "LOW")
342                                         return COST_LOW;
343                                 if(vals[m] == "HIGH")
344                                         return COST_HIGH;
345                                 if(vals[m] == "EXPENSIVE")
346                                         return COST_EXPENSIVE;
347                                 if(vals[m] == "TOP")
348                                         return COST_TOP;
349                                 fprintf(stderr,"Warning, COST %s of function %s not understood, ignoring (options are FREE, LOW, HIGH, EXPENSIVE)\n",vals[m].c_str(), fcn_name.c_str());
350                                 return COST_LOW;
351                         }
352                 }
353                 return(COST_LOW);
354         };
355
356         int estimate_fcn_cost(){
357                 int m;
358                 for(m=0;m<modifiers.size();m++){
359                         if(modifiers[m] == "COST"){
360                                 if(vals[m] == "FREE")
361                                         return 1;
362                                 if(vals[m] == "" || vals[m] == "LOW")
363                                         return 10;
364                                 if(vals[m] == "HIGH")
365                                         return 100;
366                                 if(vals[m] == "EXPENSIVE")
367                                         return 1000;
368                                 if(vals[m] == "TOP")
369                                         return 10000;
370                                 fprintf(stderr,"Warning, COST %s of function %s not understood, ignoring (options are FREE, LOW, HIGH, EXPENSIVE)\n",vals[m].c_str(), fcn_name.c_str());
371                                 return COST_LOW;
372                         }
373                 }
374                 return(COST_LOW);
375         };
376
377         std::string get_subaggr(){
378                 int m;
379                 for(m=0;m<modifiers.size();m++){
380                         if(modifiers[m] == "SUBAGGR")
381                                 return(vals[m]);
382                 }
383                 return("");
384         };
385
386         std::string get_superaggr(){
387                 int m;
388                 for(m=0;m<modifiers.size();m++){
389                         if(modifiers[m] == "SUPERAGGR")
390                                 return(vals[m]);
391                 }
392                 return("");
393         };
394         
395         std::string get_hfta_subaggr(){
396                 int m;
397                 for(m=0;m<modifiers.size();m++){
398                         if(modifiers[m] == "HFTA_SUBAGGR")
399                                 return(vals[m]);
400                 }
401                 return("");
402         };
403
404         std::string get_hfta_superaggr(){
405                 int m;
406                 for(m=0;m<modifiers.size();m++){
407                         if(modifiers[m] == "HFTA_SUPERAGGR")
408                                 return(vals[m]);
409                 }
410                 return("");
411         };      
412         
413
414         bool is_running_aggr(){
415                 int m;
416                 if(fcn_type != EXT_AGGR_)
417                         return false;
418
419                 for(m=0;m<modifiers.size();m++){
420                         if(modifiers[m] == "RUNNING")
421                                 return(true);
422                 }
423                 return(false);
424         };
425
426 //              For a special optimization,
427 //              a UDAF can say that it has no contents
428 //              worth transferring at tuple output time.
429         bool has_lfta_bailout(){
430                 int m;
431                 if(fcn_type != EXT_AGGR_)
432                         return false;
433
434                 for(m=0;m<modifiers.size();m++){
435                         if(modifiers[m] == "LFTA_BAILOUT")
436                                 return(true);
437                 }
438                 return(false);
439         };
440
441
442 //              Conventional aggregation requires only a simple
443 //              execution of the produce_output callback.  The
444 //              sampling operator might reference the output of (non-running)
445 //              aggregates      multiple times.  The MULT_RETURNS keyword
446 //              indicates that the UDAF doesn't destroy state when the
447 //              produce_output acllback is evaluated.
448         bool multiple_returns(){
449                 int m;
450                 if(fcn_type != EXT_AGGR_)
451                         return false;
452
453                 for(m=0;m<modifiers.size();m++){
454                         if(modifiers[m] == "MULT_RETURNS")
455                                 return(true);
456                 }
457                 return(false);
458         };
459
460
461         std::vector<bool> get_handle_indicators(){
462                 std::vector<bool> ret;
463                 int o;
464                 for(o=0;o<ef_param_list.size();o++){
465                         if(ef_param_list[o]->use_handle())
466                                 ret.push_back(true);
467                         else
468                                 ret.push_back(false);
469                 }
470                 return(ret);
471         };
472
473         std::vector<bool> get_const_indicators(){
474                 std::vector<bool> ret;
475                 int o;
476                 for(o=0;o<ef_param_list.size();o++){
477                         if(ef_param_list[o]->is_constant())
478                                 ret.push_back(true);
479                         else
480                                 ret.push_back(false);
481                 }
482                 return(ret);
483         }
484
485         std::vector<bool> get_class_indicators(){
486                 std::vector<bool> ret;
487                 int o;
488                 for(o=0;o<ef_param_list.size();o++){
489                         if(ef_param_list[o]->is_classifier())
490                                 ret.push_back(true);
491                         else
492                                 ret.push_back(false);
493                 }
494                 return(ret);
495         }
496
497         bool validate_types(std::string &err){
498                 int o;
499
500                 bool ret = false;
501                 if(fdt){
502                         if(fdt->get_type() == undefined_t){
503                                 err += "ERROR, unknown type "+type_name+" as return type of function "+fcn_name+"\n";
504                                 ret = true;
505                         }
506                         if(fdt->get_type() == fstring_t){
507                                 err += "ERROR, type "+type_name+" as not supported as return type, of function "+fcn_name+"\n";
508                                 ret = true;
509                         }
510                 }
511
512                 if(sdt){
513                         if(sdt->get_type() == undefined_t){
514                                 err += "ERROR, unknown type "+type_name+" as storage type of function "+fcn_name+"\n";
515                                 ret = true;
516                         }
517                 }
518
519                 std::vector<data_type *> odt = this->get_operand_dt();
520                 for(o=0;o<odt.size();++o){
521                         if(odt[o]->get_type() == undefined_t){
522                                 err += "ERROR, unknown type "+odt[o]->get_type_str()+" as operand type of function "+fcn_name+"\n";
523                                 ret = true;
524                         }
525                         if(odt[o]->get_type() == fstring_t){
526                                 err += "ERROR, type "+odt[o]->get_type_str()+" as not supported as operand type, of function "+fcn_name+"\n";
527                                 ret = true;
528                         }
529                 }
530
531                 return(ret);
532         }
533
534
535 };
536
537 class ext_fcn_list{
538 private:
539         std::vector<ext_fcn_def *> fl;
540
541 public:
542         ext_fcn_list(){};
543         ext_fcn_list(ext_fcn_def *f){
544                 fl.push_back(f);
545         };
546
547         ext_fcn_list *append_ext_fcn_def(ext_fcn_def *f){
548                 fl.push_back(f);
549                 return(this);
550         };
551
552         int lookup_ext_fcn(std::string fname, const std::vector<data_type *> odt, int type){
553                 int f, o;
554                 int subsumer = -1;
555                 int subsume_cnt;
556                 for(f=0;f<fl.size();f++){
557                         if(fl[f]->get_fcn_type() != type) continue;
558                         if(fname == fl[f]->get_fcn_name()){
559                                 subsume_cnt = 0;
560                                 std::vector<data_type *> fdt = fl[f]->get_operand_dt();
561                                 if(fdt.size() != odt.size())
562                                         continue;
563                                 for(o=0;o<odt.size();o++){
564                                         if(! fdt[o]->subsumes_type(odt[o]) )
565                                                         break;
566                                         if(! fdt[o]->equals(odt[o])) subsume_cnt++;
567                                 }
568                                 if(o == odt.size()){
569                                         if(subsume_cnt == 0)
570                                                 return(f);
571                                         if(subsumer != -1) return -2;
572                                         subsumer = f;
573                                 }
574                         }
575                 }
576                 return(subsumer);       // -1 if no subsumer found.
577         };
578
579
580         int lookup_pred(std::string fname, const std::vector<data_type *> odt){
581                 return lookup_ext_fcn(fname,odt,EXT_PRED_);
582         };
583         int lookup_fcn(std::string fname, const std::vector<data_type *> odt){
584                 return lookup_ext_fcn(fname,odt,EXT_FCN_);
585         };
586         int lookup_udaf(std::string fname, const std::vector<data_type *> odt){
587                 return lookup_ext_fcn(fname,odt,EXT_AGGR_);
588         };
589         int lookup_extr(std::string fname, const std::vector<data_type *> odt){
590                 return lookup_ext_fcn(fname,odt,EXT_EXTR_);
591         };
592         int lookup_state(std::string fname){
593                 std::vector<data_type *> dum;
594                 return lookup_ext_fcn(fname,dum,EXT_STATE_);
595         };
596         int lookup_sfun(std::string fname, const std::vector<data_type *> odt){
597                 return lookup_ext_fcn(fname,odt,EXT_SFUN_);
598         };
599
600
601
602
603
604         data_type *get_fcn_dt(int f){
605                 return(fl[f]->get_fcn_dt() );
606         };
607         data_type *get_storage_dt(int f){
608                 return(fl[f]->get_storage_dt() );
609         };
610
611         bool is_partial(int f){
612                 return(fl[f]->is_partial());
613         };
614
615         bool is_combinable(int f){
616                 return(fl[f]->is_combinable());
617         };
618
619         bool is_running_aggr(int f){
620                 return(fl[f]->is_running_aggr());
621         };
622
623         bool has_lfta_bailout(int f){
624                 return(fl[f]->has_lfta_bailout());
625         };
626
627         bool multiple_returns(int f){
628                 return(fl[f]->multiple_returns());
629         };
630
631         bool fta_legal(int f){
632                 return(fl[f]->fta_legal());
633         };
634
635         bool is_sampling_fcn(int f) {
636                 return(fl[f]->is_sampling_fcn());
637         };
638
639         int get_fcn_cost(int f) {
640                 return(fl[f]->get_fcn_cost());
641         };
642
643         int estimate_fcn_cost(int f) {
644                 return(fl[f]->estimate_fcn_cost());
645         };
646
647         int get_actual_fcn_id(int i){ return(fl[i]->get_actual_fcn_id());};
648         int get_subaggr_id(int i){ return(fl[i]->get_subaggr_id());};
649         int get_superaggr_id(int i){ return(fl[i]->get_superaggr_id());};
650         int get_hfta_subaggr_id(int i){ return(fl[i]->get_hfta_subaggr_id());};
651         int get_hfta_superaggr_id(int i){ return(fl[i]->get_hfta_superaggr_id());};     
652         int get_nparams(int i){ return(fl[i]->get_nparams());};
653         std::string get_fcn_name(int i){
654                 return fl[i]->get_fcn_name();
655         }
656         std::string get_storage_state(int i){return fl[i]->get_storage_state();};
657
658
659
660         std::vector<bool> get_handle_indicators(int f){
661                 return(fl[f]->get_handle_indicators());
662         };
663         std::vector<bool> get_const_indicators(int f){
664                 return(fl[f]->get_const_indicators());
665         };
666         std::vector<bool> get_class_indicators(int f){
667                 return(fl[f]->get_class_indicators());
668         };
669
670         bool validate_fcns(std::string &err){
671           int e, f;
672           int subaggr_id, superaggr_id, hfta_subaggr_id, hfta_superaggr_id;
673
674 //              First, validate that all data types exist and are valid.
675
676           int retval = 0;
677           for(e=0;e<fl.size();++e){
678                 if(fl[e]->validate_types(err)) retval = 1;
679           }
680           if(retval) return(true);
681
682 //              validate combinable predicates
683           for(e=0;e<fl.size();++e){
684                         if(fl[e]->is_pred() && fl[e]->is_combinable()){
685                         std::vector<bool> hlv = fl[e]->get_handle_indicators();
686                         std::vector<bool> cov = fl[e]->get_const_indicators();
687                         std::vector<bool> clv = fl[e]->get_class_indicators();
688                         int i;
689                         for(i=0;i<hlv.size();++i){
690                                 if( hlv[i] == false && cov[i] == false && clv[i] == false)
691                                         break;
692                         }
693                         if(i<hlv.size()){
694                                 err += "ERROR, in combinable predicate  "+fl[e]->get_fcn_name()+", there is a parameter that is not a CLASS-ification parameter, but neither is it CONST nor HANDLE.\n";
695                                 retval = 1;
696                                 for(i=0;i<hlv.size();++i){
697                                         printf("\t%d: h=%d, co=%d, cl=%d\n",i,(int)hlv[i],(int)cov[i],(int)clv[i]);
698                                 }
699                         }
700                         }
701                 }
702                 
703                                 
704
705 //              validate the states of the stateful functions.
706           for(e=0;e<fl.size();++e){
707                 if(fl[e]->is_sfun()){
708                         std::string sstate = fl[e]->get_storage_state();
709                         if(lookup_state(sstate) < 0){
710                                 err += "ERROR, stateful function "+fl[e]->get_fcn_name()+" has state "+sstate+", which is not defined.\n";
711                                 retval = 1;
712                                 continue;
713                         }
714                 }
715           }
716
717 //              Validate subaggregates and superaggregates of udafs
718
719           for(e=0;e<fl.size();++e){
720                 if(fl[e]->is_udaf()){
721                         std::string subaggr = fl[e]->get_subaggr();
722                         std::string superaggr = fl[e]->get_superaggr();
723                         if(subaggr != "" || superaggr != ""){
724                                 if(subaggr == "" || superaggr == ""){
725                                         err += "ERROR, aggregate "+fl[e]->get_fcn_name()+" has a sub or superaggregate specified, but not both.\n";
726                                         retval = 1;
727                                         continue;
728                                 }
729                                 subaggr_id=lookup_udaf(subaggr, fl[e]->get_operand_dt());
730                                 if(subaggr_id < 0){
731                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a subaggregate specified, but it can't be found.\n";
732                                         if(subaggr_id == -2) err+="(multiple subsuming subaggrs found)\n";
733                                         retval=1;
734                                         continue;
735                                 }
736                                 std::vector<data_type *> dtv;
737                                 dtv.push_back( fl[subaggr_id]->get_fcn_dt() );
738                                 superaggr_id=lookup_udaf(superaggr, dtv);
739                                 if(superaggr_id < 0){
740                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a superaggregate specified, but it can't be found.\n";
741                                         if(subaggr_id == -2) err+="(multiple subsuming superaggrs found)\n";
742                                         retval=1;
743                                         continue;
744                                 }
745
746                                 if( fl[e]->is_running_aggr() != fl[superaggr_id]->is_running_aggr()){
747                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a superaggregate specified, but  one is a running aggregate and the other isn't\n";
748 //printf("e=%d (%u), superaggr_id=%d (%u)\n",e, fl[e]->is_running_aggr(),superaggr_id,fl[superaggr_id]->is_running_aggr());
749                                         retval=1;
750                                         continue;
751                                 }
752
753                                 if(! fl[e]->get_fcn_dt()->equals(fl[superaggr_id]->get_fcn_dt())){
754                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a superaggregate specified, but they have different return types.\n";
755                                         retval=1;
756                                         continue;
757                                 }
758
759                                 if(fl[subaggr_id]->get_subaggr()!="" || fl[subaggr_id]->get_superaggr() != ""){
760                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a subaggregate specified, but it also has sub/super aggregates\n";
761                                         retval=1;
762                                         continue;
763                                 }
764                                 if(fl[superaggr_id]->get_subaggr()!="" || fl[superaggr_id]->get_superaggr() != ""){
765                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a subaggregate specified, but it also has sub/super aggregates\n";
766                                         retval=1;
767                                         continue;
768                                 }
769
770                                 fl[e]->set_subaggr_id(subaggr_id);
771                                 fl[e]->set_superaggr_id(superaggr_id);
772                         }
773                 }
774           }
775           
776 //              Validate high level subaggregates and superaggregates of udafs (hfta_subaggregate and hfta_supeaggregate)
777
778           for(e=0;e<fl.size();++e){
779                 if(fl[e]->is_udaf()){
780                         std::string hfta_subaggr = fl[e]->get_hfta_subaggr();
781                         std::string hfta_superaggr = fl[e]->get_hfta_superaggr();
782                         if(hfta_subaggr != "" || hfta_superaggr != ""){
783                                 if(hfta_subaggr == "" || hfta_superaggr == ""){
784                                         err += "ERROR, aggregate "+fl[e]->get_fcn_name()+" has a hfta_sub or hfta_superaggregate specified, but not both.\n";
785                                         retval = 1;
786                                         continue;
787                                 }
788                                 hfta_subaggr_id=lookup_udaf(hfta_subaggr, fl[e]->get_operand_dt());
789                                 if(hfta_subaggr_id < 0){
790                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a hfta_subaggregate specified, but it can't be found.\n";
791                                         if(subaggr_id == -2) err+="(multiple subsuming hfta_subaggrs found)\n";
792                                         retval=1;
793                                         continue;
794                                 }
795                                 std::vector<data_type *> dtv;
796                                 dtv.push_back( fl[hfta_subaggr_id]->get_fcn_dt() );
797                                 hfta_superaggr_id=lookup_udaf(hfta_superaggr, dtv);
798                                 if(hfta_superaggr_id < 0){
799                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a hfta_superaggregate specified, but it can't be found.\n";
800                                         if(hfta_subaggr_id == -2) err+="(multiple subsuming hfta_superaggrs found)\n";
801                                         retval=1;
802                                         continue;
803                                 }
804
805                                 if(! fl[e]->get_fcn_dt()->equals(fl[hfta_superaggr_id]->get_fcn_dt())){
806                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a hfta_superaggregate specified, but they have different return types.\n";
807                                         retval=1;
808                                         continue;
809                                 }
810                                 
811                                 /*
812
813                                 if(fl[hfta_subaggr_id]->get_hfta_subaggr()!="" || fl[hfta_subaggr_id]->get_hfta_superaggr() != ""){
814                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a hfta_subaggregate specified, but it also has hfta sub/super aggregates\n";
815                                         retval=1;
816                                         continue;
817                                 }
818                                 if(fl[hfta_superaggr_id]->get_hfta_subaggr()!="" || fl[hfta_superaggr_id]->get_hfta_superaggr() != ""){
819                                         err+="ERROR, aggregate "+fl[e]->get_fcn_name()+" has a hfta_subaggregate specified, but it also has hfta sub/super aggregates\n";
820                                         retval=1;
821                                         continue;
822                                 }
823                                 */
824
825                                 fl[e]->set_hfta_subaggr_id(hfta_subaggr_id);
826                                 fl[e]->set_hfta_superaggr_id(hfta_superaggr_id);
827                         }
828                 }
829           }       
830
831 //                      Verify the extraction functions
832           for(e=0;e<fl.size();++e){
833                 if(fl[e]->is_extr()){
834 //printf("Verifying extractor %d\n",e);
835                         std::vector<data_type *> ope = fl[e]->get_operand_dt();
836 //                              Find the subaggregate
837                         int a;
838                         for(a=0;a<fl.size();++a){
839                                 if(fl[a]->is_udaf() && fl[e]->get_udaf_name() == fl[a]->get_fcn_name()){
840 //printf("matching to subaggregagte %d\n",a);
841                                         std::vector<data_type *> opa = fl[a]->get_operand_dt();
842                                         if(opa.size() > ope.size()) continue;
843                                         int o;
844                                         bool match_ops = true;
845                                         for(o=0;o<opa.size();++o){
846                                                 if(! ope[o]->equals(opa[o])) match_ops = false;
847 //else printf("\tmatched operand %d\n",o);
848                                         }
849                                         if(match_ops) break;
850 //else printf("subaggregate match failed.\n");
851                                 }
852                         }
853                         if(a>=fl.size()){
854                                 err+="ERROR, aggregate extractor "+fl[e]->get_fcn_name()+" has a subaggregate "+ fl[e]->get_udaf_name()+" specified, but it can't be found.\n";
855                                 retval=1;
856                                 continue;
857                         }
858
859 //                              Found the subaggregate
860                         subaggr_id = a;
861                         std::vector<data_type *> opa = fl[a]->get_operand_dt();
862
863 //                              Find the actual function
864                         for(f=0;f<fl.size();++f){
865                                 if(fl[f]->is_fcn() && fl[e]->get_actual_fcn() == fl[f]->get_fcn_name()){
866 //printf("Matching to extraction function %d\n",f);
867                                         std::vector<data_type *> opf = fl[f]->get_operand_dt();
868                                         if(opf.size() + opa.size() -1 != ope.size()) continue;
869 //else printf("Operand sizes match (%d + %d -1 = %d)\n",opf.size(),opa.size(),ope.size() );
870                                         int o;
871                                         bool match_ops = true;
872                                         if(! fl[a]->get_fcn_dt()->equals(opf[0])) match_ops=false;
873 //if(!match_ops) printf("aggr return val doesn't match 1st param\n");
874                                         for(o=1;o<opf.size();++o){
875                                                 if(! ope[o+opa.size()-1]->equals(opf[o]))
876                                                         match_ops = false;
877 //else printf("\tmatched operand e[%d] to f[%d]\n",o+opa.size()-1,o);
878                                         }
879                                         if(match_ops) break;
880 //else printf("Match failed.\n");
881                                 }
882                         }
883                         if(f>=fl.size()){
884                                 err+="ERROR, aggregate extractor "+fl[e]->get_fcn_name()+" uses function "+ fl[e]->get_actual_fcn()+", but it can't be found.\n";
885                                 retval=1;
886                                 continue;
887                         }
888                         if(! fl[e]->get_fcn_dt()->equals(fl[f]->get_fcn_dt()) ){
889                                 err+="ERROR, aggregate extractor "+fl[e]->get_fcn_name()+" uses function "+ fl[e]->get_actual_fcn()+", but they have different return value types.\n";
890                                 retval=1;
891                                 continue;
892                         }
893
894 //                              Found the extractor fcn, record them in the ext fcn struct.
895                         fl[e]->set_subaggr_id(subaggr_id);
896                         fl[e]->set_actual_fcnid(f);
897                 }
898           }
899
900           if(retval) return(true); else return(false);
901         };
902
903
904 };
905
906
907 #endif