/******************************************************************************** * * The interpreter for the code produced by the code generator. * Copyright (c) 1999-2003 by Leonidas Fegaras, the University of Texas at * Arlington. All rights reserved. * Programmer: Leonidas Fegaras, UTA * Date: 8/23/99 * *********************************************************************************/ #ifdef LDB_SERVER #include #else #include # endif #include "odl.h" #include "eval.h" #include "typecheck.h" #include "constant.h" #include /* set it to true to trace the interpreter */ const bool TRACE = false; /* Interface to flex (to scan a string) */ typedef struct yy_buffer_state *YY_BUFFER_STATE; YY_BUFFER_STATE yy_scan_string( const char* ); void yy_delete_buffer ( YY_BUFFER_STATE ); extern int parser_line; /* Ask the parser to parse an OQL query (in oql.y) */ void parse_oql(); /* catching exceptions */ #define DEBUG(exp) catch (odmg_error_class(m)) \ { eout << "*** Found in " << exp << '\n'; \ throw odmg_error_class(eout.str()); } /* An OQL query produced by the OQL parser (in oql.y) */ extern Expr OQL_query; /* should be true when interpreting OQL queries */ extern bool interpreterp; /* defined in code_generator.gen */ int size_in_bytes ( Expr tp, bool is_raw_data = false ); int add_sizes ( int n, int m); int round_size ( int n ); Expr expand_type ( Expr tp ); extern String current_module_name; /* global environment for group-by vars */ extern GEnv gvars; extern Schema gbinds; /* returns the physical plan with the smallest cost -- defined in cost_optimizer.gen */ Expr best_evaluation_order ( Expr e ); Expr last ( list* r ); typedef struct { char* name; void* address; short args; short fncs; } function_table_element; const int function_table_size = 1000; /* in case of RPC connection, limit the output size to 10KB */ bool rpc_printer_limitation = false; extern int function_table_top; extern function_table_element function_table[function_table_size]; static int debug_nesting = 0; static void* lambda_functions[10][3]; static int fncs_top = 0; static Expr fncs_stack[function_table_size]; void push_fnc ( Expr e ) { fncs_stack[fncs_top++] = e; if (fncs_top >= function_table_size) odmg_error("Overflow stack of lambda abstractions"); }; void pop_fncs ( short n ) { fncs_top -= n; if (fncs_top < 0) odmg_error("Trying to pop an empty stack of lambda abstractions"); }; int lambda_num_top = 0; short lambda_num_stack[1000]; void push_lambda_num ( short k ) { lambda_num_stack[lambda_num_top++] = k; }; void pop_lambda_num () { lambda_num_top--; }; tuple eval_none () { return NULL; }; static void* false_value = (void*) new (GC) bool(false); static void* true_value = (void*) new (GC) bool(true); static binding* global_env; static binding* static_env = new binding; typedef struct union_cell { short tag; } union_cell; static int* tuple_identifier = new int(0); #define E ( r = r->tl, eval_expr(r->hd,env,coercep) ) void* eval_expr ( Expr e, binding* env, bool coercep ); void* coerce_values ( void* x, Expr tp, binding* env ) { #case tp | string => return new (GC) sm_string(*(raw_string*) x); | `v : v->variablep() && classp(v->name()) => return new (GC) sm_ref(*(raw_ref*) x); | `f(string) : collectionp(f) => return new (GC) Sequence(Sequence(*(raw_sequence*) x)); | `f(`v) : collectionp(f) => return new (GC) Sequence((Sequence)(*(raw_sequence*) x)); | struct(`nm,...r) : nm->variablep() => return coerce_values(x,#,env); | struct(...r) => { void** v = new (GC) (void*)[r->length()+1]; // the first element of the vector is a fixed address (used as a tag to help the printer recognize it) v[0] = (void*) &tuple_identifier; binding* new_env = env->extend(#->name(),x); int offset = 0; for(short i = 1; r->consp(); r=r->tl, i++) #case r->hd | bind(`w,`etp) => { v[i] = eval_expr(#,new_env,true); offset = add_sizes(offset,size_in_bytes(etp,true)); }; #end; return (void*) v; }; | scope(`nm) => return coerce_values(x,get_declaration_binding(nm->name()),env); | _ => return x; #end; }; /* evaluate an OQL operation */ void* eval_expr ( Expr e, binding* env, bool coercep ) { static int suspend_fnc_loc = find_function("suspended_stream"); static int nested_fnc_loc = find_function("nested_collection_stream_with_closure"); try{ void* res = NULL; #case e | value(`x,`tp) => res = eval_expr(x,env,coercep); | stream(`v) => res = env->find(v->name()); | empty_collection(`tp,`n) => res = (void*) new (GC) sm_sequence((size_t) n->info.Integer); | new_tuple_reference(`x) => res = (void*) new Tuple((sm_ref*) eval_expr(x,env,coercep)); | new_tuple_value(`x) => res = (void*) new Tuple((void*) eval_expr(x,env,coercep)); | tuple_value(`x,`n,_) => res = (void*) (*(tuple) eval_expr(x,env,coercep))[n->info.Integer].value(); | tuple_reference(`x,`n,`tp) => res = (sm_ref*) (*(tuple) eval_expr(x,env,coercep))[n->info.Integer].reference(); | assign(...r) => for(; r->consp(); r=r->tl) #case r->hd | bind(`v,call(1,`loc,lambda(0,`body)),stream) : (loc->info.Integer == suspend_fnc_loc) => { lambda_closure* c = new (GC) lambda_closure; c->body = (void*) body; c->environment = (void*) env; Stream* s = suspended_stream(&eval_none); s->set_closure(c); env = env->extend(v->name(),(void*) s); }; | bind(`v,`e,_) => env = env->extend(v->name(),eval_expr(e,env,coercep)); | static_bind(`v,`e,`test,_) => if (*(bool*) eval_expr(test,env,coercep)) static_env = static_env->extend(v->name(),eval_expr(e,env,coercep)); | `u => res = eval_expr(u,env,coercep); #end; | if(`c,`x,`y) // lazy => if (*(bool*) eval_expr(c,env,coercep)) res = eval_expr(x,env,coercep); else res = eval_expr(y,env,coercep); | eq_oid(`x,`y) => { void* nx = eval_expr(x,env,coercep); void* ny = eval_expr(y,env,coercep); res = (void*) new (GC) bool((nx == NULL && ny == NULL) || (nx != NULL && ny != NULL && ((sm_ref*)nx)->valid() && ((sm_ref*)ny)->valid() && (((oid_t)((sm_ref*)nx)->oid()) == ((oid_t)((sm_ref*) ny)->oid())))); }; | call(2,`loc,`x,lambda(2,`body)) : (LDB_LINUX && loc->info.Integer == nested_fnc_loc) => { lambda_closure* c = new (GC) lambda_closure; c->body = (void*) body; c->environment = (void*) env; res = (void*) nested_collection_stream_with_closure(c,(tuple) eval_expr(x,env,coercep)); }; | call(2,`loc,lambda(2,`body),`x) : (loc->info.Integer == nested_fnc_loc) => { lambda_closure* c = new (GC) lambda_closure; c->body = (void*) body; c->environment = (void*) env; res = (void*) nested_collection_stream_with_closure(c,(tuple) eval_expr(x,env,coercep)); }; | call(`n,...r) => { short len = n->info.Integer; // number of arguments int loc = r->hd->info.Integer; // location of code if (loc<0) odmg_error("illegal function call"); short lambdas = function_table[loc].fncs; // number of lambda arguments push_lambda_num(lambdas); // allocate space for lambda arguments global_env = env; void* f = function_table[loc].address; // pointer to code to evaluate the function body if (TRACE) { for(int i=0; i* s=r->tl; s->consp(); s=s->tl) #case s->hd | lambda(...k) => i++; #end; if (i != lambdas) odmg_error("wrong number of lambda arguments",e); debug_nesting++; }; switch (len) { case 0: res = ((void*(*)()) f)(); break; case 1: res = ((void*(*)(void*)) f)(E); break; case 2: res = ((void*(*)(void*,void*)) f)(E,E); break; case 3: res = ((void*(*)(void*,void*,void*)) f)(E,E,E); break; case 4: res = ((void*(*)(void*,void*,void*,void*)) f)(E,E,E,E); break; case 5: res = ((void*(*)(void*,void*,void*,void*,void*)) f)(E,E,E,E,E); break; case 6: res = ((void*(*)(void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E); break; case 7: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E); break; case 8: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E); break; case 9: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E); break; case 10: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E); break; case 11: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E); break; case 12: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E); break; case 13: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E); break; case 14: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E,E); break; case 15: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E,E,E); break; case 16: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E); break; case 17: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E); break; case 18: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E); break; case 19: res = ((void*(*)(void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*,void*)) f)(E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E,E); break; default: odmg_error("Too many parameters in function call",e); }; pop_fncs(lambdas); pop_lambda_num(); if (TRACE) { debug_nesting--; for(int i=0; i " << function_table[loc].name << ": " << res << endl; }; }; | lambda(`n,`body) => { push_fnc(body); res = lambda_functions[lambda_num_stack[lambda_num_top-1]--][n->info.Integer]; }; | struct(_,_,...r) => { void** v = new (GC) (void*)[r->length()+1]; // the first element of the vector is a fixed address (used as a tag to help the printer recognize it) v[0] = (void*) &tuple_identifier; for(short i = 1; r->consp(); r=r->tl, i++) v[i] = eval_expr(r->hd->arguments()->tl->hd,env,coercep); res = (void*) v; }; | project(`x,`f,`n,`tp,`rtp,...r) => { res = eval_expr(x,env,true); if (((void**) res)[0] == (void*) &tuple_identifier) // constructed by interpreter's struct if (r->consp()) res = ((void**) res)[r->hd->info.Integer]; else res = ((void**) res)[n->info.Integer+1]; else { if (rtp->variablep() && classp(rtp->name())) res = ((char*) ((sm_ref*) res)->deref(sizeof(rtp,true))) + n->info.Integer; else res = ((char*) res) + n->info.Integer; if (coercep) res = coerce_values(res,tp,env); }; }; | union_tag(`x) => res = (void*) (new (GC) long(((union_cell*) eval_expr(x,env,coercep))->tag)); | union_case(`x,_,_,`n) => res = ((char*) eval_expr(x,env,coercep)) + (n->info.Integer); | union_construction(_,`tag,_,`value,_,_,`offset,`vsize,`usize) => { pinned_object* _co = current_object; current_object = new (GC) pinned_object(usize->info.Integer); const char* val = current_object->get(0,usize->info.Integer); (*(type_tag*) val) = *(type_tag*) eval_expr(tag,env,coercep); copy_n_bytes((char*) (val+offset->info.Integer), (char*) eval_expr(value,env,coercep),vsize->info.Integer); current_object = _co; res = (void*) val; }; | update(project(`x,`v,`n,_,`rtp,...r),empty_collection(_,`m),_,_) => { ((sm_ref*) eval_expr(x,env,true))->deref(sizeof(rtp,true)); raw_sequence x; x.element_size = m->info.Integer; x.cardinality = 0; x.offset = 0; set_current_object(n->info.Integer,sizeof(raw_sequence),(char*) &x); }; | update(`d,`s,`tp,`n) => { char* source = (char*)eval_expr(s,env,coercep); if (source) #case expand_type(tp) | string => { char* dest = (char*)eval_expr(d,env,false); sm_string(*(raw_string*) dest) = *(sm_string*) source; }; | `f(string) : collectionp(f) => { char* dest = (char*)eval_expr(d,env,false); (Sequence)(*(raw_sequence*) dest) = *(Sequence*) source; }; | `f(`v) : collectionp(f) && v->variablep() && classp(v->name()) => { char* dest = (char*)eval_expr(d,env,false); (Sequence)(*(raw_sequence*) dest) = *(Sequence*) source; }; | `f(_) : collectionp(f) => { char* dest = (char*)eval_expr(d,env,false); *(raw_sequence*) dest = *(sm_sequence*) source; }; | `v : v->variablep() && classp(v->name()) => { char* dest = (char*)eval_expr(d,env,false); *(raw_ref*) dest = *(sm_ref*) source; }; | _ => { char* dest = (char*)eval_expr(d,env,false); copy_n_bytes(dest,source,n->info.Integer); }; #end; }; | sequence_insert(project(`x,`v,`n,`f(`tp),`rtp,...r),`e) : collectionp(f) && tp->variablep() && classp(tp->name()) && rtp->variablep() && classp(rtp->name()) => { raw_ref s = (raw_ref) *(sm_ref*) eval_expr(e,env,coercep); (new (GC) Sequence(*(raw_sequence*)(((char*) ((sm_ref*) eval_expr(x,env,true)) ->deref(sizeof(rtp,true))) + n->info.Integer)))->insert(s); }; | sequence_insert(`d,`e) => { void* s = eval_expr(e,env,coercep); (new (GC) sm_sequence(*(raw_sequence*) eval_expr(d,env,false)))->append((const char*) s); }; | sequence_remove(project(`x,`v,`n,`f(`tp),`rtp,...r),`e) : collectionp(f) && tp->variablep() && classp(tp->name()) && rtp->variablep() && classp(rtp->name()) => { raw_ref s = (raw_ref) *(sm_ref*) eval_expr(e,env,coercep); (new (GC) Sequence(*(raw_sequence*)(((char*) ((sm_ref*) eval_expr(x,env,true)) ->deref(sizeof(rtp,true))) + n->info.Integer)))->remove(s); }; | sequence_remove(`d,`e) => { void* s = eval_expr(e,env,coercep); (new (GC) sm_sequence(*(raw_sequence*) eval_expr(d,env,false)))->remove((const char*) s); }; | map(`x,_,`f,`set) => { sm_sequence* sm = (sm_sequence*) eval_expr(set,env,coercep); for (int i=0; icardinality(); i++) eval_expr(f,env->extend(x->name(),(void*)sm->access(i)),coercep); }; | block(...r) => { binding* new_env = env; for(; r->tl->consp(); r=r->tl) #case r->hd | define(`v,`u,`tp) => { void* val = eval_expr(u,new_env,coercep); new_env = new_env->extend(v->name(),val); }; | _ => eval_expr(r->hd,new_env,coercep); #end; res = eval_expr(r->hd,new_env,coercep); }; | LDBobject(`n) => { res = LDBobject(n->info.Integer).getvalue(); if (res == NULL) odmg_error("Can't find object",e); }; | method_call(`nm,...args) => #case get_declaration_binding(nm->name()); | lambda(_,...binds,`body) => { binding* new_env = env; for(list* r = binds; r->consp(); r=r->tl, args=args->tl) #case r->hd | bind(`v,`etp) => new_env = new_env->extend(v->name(),eval_expr(args->hd,env,coercep)); #end; res = eval_expr(body,new_env,coercep); }; | _ => odmg_error("There is no implementation for method",e); #end; | true => res = true_value; | false => res = false_value; | NULL => res = NULL; | null => res = new int(0); | nil => res = new int(0); | _ => if (e->integerp()) res = (void*) new (GC) long(e->info.Integer); else if (e->stringp()) res = (void*) new (GC) sm_string(e->info.Estring->content()); else if (e->realp()) res = (void*) new (GC) float(e->info.Real); else if (e->variablep() && env->in(e->name())) res = env->find(e->name()); else if (e->variablep() && static_env->in(e->name())) res = static_env->find(e->name()); else odmg_error("Don't know how to evaluate",e); #end; return res; } DEBUG(e); }; void* evaluate_expr ( void* code ) { return eval_expr((Expr) code,new binding,true); }; Expr preprocess_expr ( Expr e ); list* preprocess_expr_list ( list* r ) { if (r->nullp()) return Nil; else return Cons(preprocess_expr(r->hd),preprocess_expr_list(r->tl)); }; Expr preprocess_expr ( Expr e ) { #case e | call(`nm,`loc,...r) => { list* s = preprocess_expr_list(r); /*** due to a bug, linux g++ pushes void*(*)(...) */ /*** arguments in reverse order */ if (LDB_LINUX) s = s->reverse(); if (loc->info.Integer<0) odmg_error("undefined function",nm); else return #length())),`loc,...s)>; }; | internal_call(`nm,`loc,_,...r) => return preprocess_expr(#); | update(`d,`s,`tp) => return #; | lambda(`tp,...r) => return #length()-1)),`(preprocess_expr(last(r))))>; | `f(...r) => { list* s = preprocess_expr_list(r); return #<`f(...s)>; }; | _ => return e; #end; }; const String X_ = new string("x"); const String Y_ = new string("y"); void* eval_expr_10 () { return eval_expr(fncs_stack[fncs_top-1],global_env,true); }; void* eval_expr_11 ( void* x ) { return eval_expr(fncs_stack[fncs_top-1],global_env->extend(X_,x),true); }; void* eval_expr_12 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-1],global_env->extend(X_,x)->extend(Y_,y),true); }; void* eval_expr_20 () { return eval_expr(fncs_stack[fncs_top-2],global_env,true); }; void* eval_expr_21 ( void* x ) { return eval_expr(fncs_stack[fncs_top-2],global_env->extend(X_,x),true); }; void* eval_expr_22 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-2],global_env->extend(X_,x)->extend(Y_,y),true); }; void* eval_expr_30 () { return eval_expr(fncs_stack[fncs_top-3],global_env,true); }; void* eval_expr_31 ( void* x ) { return eval_expr(fncs_stack[fncs_top-3],global_env->extend(X_,x),true); }; void* eval_expr_32 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-3],global_env->extend(X_,x)->extend(Y_,y),true); }; void* eval_expr_40 () { return eval_expr(fncs_stack[fncs_top-4],global_env,true); }; void* eval_expr_41 ( void* x ) { return eval_expr(fncs_stack[fncs_top-4],global_env->extend(X_,x),true); }; void* eval_expr_42 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-4],global_env->extend(X_,x)->extend(Y_,y),true); }; void* eval_expr_50 () { return eval_expr(fncs_stack[fncs_top-5],global_env,true); }; void* eval_expr_51 ( void* x ) { return eval_expr(fncs_stack[fncs_top-5],global_env->extend(X_,x),true); }; void* eval_expr_52 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-5],global_env->extend(X_,x)->extend(Y_,y),true); }; void* eval_expr_60 () { return eval_expr(fncs_stack[fncs_top-6],global_env,true); }; void* eval_expr_61 ( void* x ) { return eval_expr(fncs_stack[fncs_top-6],global_env->extend(X_,x),true); }; void* eval_expr_62 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-6],global_env->extend(X_,x)->extend(Y_,y),true); }; void* eval_expr_70 () { return eval_expr(fncs_stack[fncs_top-7],global_env,true); }; void* eval_expr_71 ( void* x ) { return eval_expr(fncs_stack[fncs_top-7],global_env->extend(X_,x),true); }; void* eval_expr_72 ( void* x, void* y ) { return eval_expr(fncs_stack[fncs_top-7],global_env->extend(X_,x)->extend(Y_,y),true); }; void init_lambda_functions () { lambda_functions[1][0] = (void*) eval_expr_10; lambda_functions[1][1] = (void*) eval_expr_11; lambda_functions[1][2] = (void*) eval_expr_12; lambda_functions[2][0] = (void*) eval_expr_20; lambda_functions[2][1] = (void*) eval_expr_21; lambda_functions[2][2] = (void*) eval_expr_22; lambda_functions[3][0] = (void*) eval_expr_30; lambda_functions[3][1] = (void*) eval_expr_31; lambda_functions[3][2] = (void*) eval_expr_32; lambda_functions[4][0] = (void*) eval_expr_40; lambda_functions[4][1] = (void*) eval_expr_41; lambda_functions[4][2] = (void*) eval_expr_42; lambda_functions[5][0] = (void*) eval_expr_50; lambda_functions[5][1] = (void*) eval_expr_51; lambda_functions[5][2] = (void*) eval_expr_52; lambda_functions[6][0] = (void*) eval_expr_60; lambda_functions[6][1] = (void*) eval_expr_61; lambda_functions[6][2] = (void*) eval_expr_62; lambda_functions[7][0] = (void*) eval_expr_70; lambda_functions[7][1] = (void*) eval_expr_71; lambda_functions[7][2] = (void*) eval_expr_72; }; static int init_lambdas = (init_lambda_functions(), 0); Expr translate ( Expr e ); Expr optimize_query ( Expr query ); Expr translate_query ( Expr e, Schema &sch, Schema &stuple, bool streamp = true ); class plan: public gc { private: Expr plan_code; Expr plan_type; public: plan ( const char* query, short level ); plan::plan ( const char* stmt ); void* evaluate (); void print_type (); void print_value ( void* value, short max_depth ); }; Expr no_void_type ( Expr e ) { #case e | void(`x) => return no_void_type(x); | scope(`x) => return no_void_type(x); | `f(...r) => { list* s = Nil; for(; r->consp(); r=r->tl) s = s->cons(no_void_type(r->hd)); s = s->reverse(); return #<`f(...s)>; }; | _ => return e; #end; }; void return_null ( int n ) { if (n==SIGFPE) throw odmg_error_class("*** Floating point exception error.\n"); else throw odmg_error_class("*** Fatal System Error.\n"); }; void LDB_statement ( const char* stmt ) { signal(SIGFPE,return_null); signal(SIGSEGV,return_null); interpreterp = false; YY_BUFFER_STATE buffer = yy_scan_string(stmt); parse_oql(); }; plan::plan ( const char* query, short level ) : plan_type(NULL) { signal(SIGFPE,return_null); signal(SIGSEGV,return_null); interpreterp = true; YY_BUFFER_STATE buffer = yy_scan_string(fform("%%n := %s;\n",query)); parse_oql(); Expr e = OQL_query->arguments()->tl->hd; Expr u = translate(e); Schema vars = new binding; plan_type = type_of(u,vars,true,true); if (level>0) { cout << "Comprehension Calculus Form:\n"; u->pretty_print(0,cout); cout << endl; cout << "\nType of the Query: " << no_void_type(plan_type); }; Expr oq = optimize_query(u); if (level>0) { cout << "\n\nOptimized Algebraic Form:\n"; oq->pretty_print(0,cout); }; Expr pq = best_evaluation_order(oq); if (level>0) { cout << "\n\nPhysical Plan:\n"; pq->pretty_print(0,cout); }; Schema sch = new binding; Schema stuple = new binding; gvars = new list*>; gbinds = new binding; plan_code = translate_query(pq,sch,stuple,false); if (level>1) { cout << "\n\nEvaluation Code:\n"; plan_code->pretty_print(0,cout); cout << "\n\n"; }; plan_code = preprocess_expr(plan_code); yy_delete_buffer(buffer); }; void process_oql ( Expr e ); plan::plan ( const char* stmt ) : plan_type(NULL) { signal(SIGFPE,return_null); signal(SIGSEGV,return_null); interpreterp = true; YY_BUFFER_STATE buffer = yy_scan_string(fform("%%%s;\n",stmt)); parse_oql(); Expr e = OQL_query; Expr u = translate(e); Schema vars = new binding; plan_type = type_of(u,vars,true,true); Expr oq = optimize_query(u); Expr pq = best_evaluation_order(oq); Schema sch = new binding; Schema stuple = new binding; gvars = new list*>; gbinds = new binding; plan_code = translate_query(pq,sch,stuple,false); plan_code = preprocess_expr(plan_code); yy_delete_buffer(buffer); }; void* plan::evaluate () { void* res = NULL; signal(SIGFPE,return_null); signal(SIGSEGV,return_null); return evaluate_expr(plan_code); }; void plan::print_type () { cout << plan_type << endl; }; Expr union_case_type ( Expr tag, list* cases ) { for(list* r = cases; r->consp(); r=r->tl) #case r->hd | case(`ctp,`decl,...tags) : member(tag,tags) => return ctp; | case(`ctp,`decl,default) => return ctp; #end; return #; }; int union_case_offset ( Expr tag, list* cases, bool raw_data_p ) { int offset = sizeof(type_tag); for(list* r = cases; r->consp(); r=r->tl) #case r->hd | case(`ctp,`decl,...tags) : member(tag,tags) => return offset; | case(`ctp,`decl,...tags) => offset = add_sizes(offset,size_in_bytes(ctp,raw_data_p)); #end; return 0; }; static void spaces ( int tab, ostream &fout ) { for(int i = 0; i 9000) { fout << "..."; return; }; static int xml_printer = find_function("print_xml_element"); if (value == NULL) fout << "NULL"; else #case type | struct(`v,...r) : v->variablep() => print_value(#,value,tab,max_depth,true,fout); | struct(...r) => { fout << "struct("; int size = 0; bool tuplep = (((void**) value)[0] == (void*) &tuple_identifier); for(int i = 1; r->consp(); r=r->tl, i++) #case r->hd | bind(`attr,`tp) => { fout << attr << ": "; // HACK: if the first element is a specific pointer (tuple_identifier), it's a constructed struct if (tuplep) { print_value(tp,((void**) value)[i], tab+(attr->name()->length())+9,max_depth,raw_data_p,fout); } else { void* val = ((char*) value) + round_size(size); size = add_sizes(size,size_in_bytes(tp,raw_data_p)); print_value(tp,val,tab+(attr->name()->length())+9,max_depth,raw_data_p,fout); }; if (r->tl->consp()) { fout << ",\n"; spaces(tab+7,fout); }; }; #end; fout << ")"; }; | void(`tp) => print_value(tp,value,tab,max_depth,raw_data_p,fout); | scope(`v) => print_value(v,value,tab,max_depth,raw_data_p,fout); | enum(_,...r) => fout << r->nth((*(long*) value)+1); | union(`nm,`tp,...cases) => { short tag = *((int*) value); list* utags = get_union_tags(tp); Expr ctag = (utags->consp()) ? utags->nth(tag+1) : integer(tag); fout << nm << "(" << ctag << ": "; print_value(union_case_type(#,cases), ((char*)value)+union_case_offset(#,cases,raw_data_p), tab+(nm->name()->length())+(ctag->name()->length())+3, max_depth,raw_data_p,fout); fout << ")"; }; | LDBobject(`n) => fout << LDBobject(n->info.Integer).toString(); | `f(`tp) => { set_current_object(); sm_sequence* s = (!raw_data_p) ? ((sm_sequence*) value) : new (GC) sm_sequence(*((raw_sequence*) value)); int fsize = f->name()->length()+1; fout << f << "("; int card = 100 cardinality(); if (max_depth <= 0 && card>0) fout << "#" << s->cardinality(); else for(int i = 0; i 9000) { fout << "...)"; return; } else { set_current_object(); print_value(tp,(void*)s->access(i),tab+fsize,max_depth-1,raw_data_p,fout); if (icardinality()>100) { fout << ",\n"; spaces(tab+fsize,fout); fout << "..."; }; fout << ")"; }; | string => if (!raw_data_p) fout << "\"" << *(sm_string*) value << "\""; else { set_current_object(); fout << "\"" << sm_string(*(raw_string*) value) << "\""; }; | integer => fout << *(long*) value; | long => fout << *(long*) value; | int => fout << *(long*) value; | short => fout << *(short*) value; | unsigned_short => fout << *(unsigned long*) value; | unsigned_long => fout << *(unsigned long*) value; | real => fout << *(float*) value; | float => fout << *(float*) value; | double => fout << *(double*) value; | boolean => fout << ((*(bool*) value) ? "true" : "false"); | XML_element // print XML data in XML form : (xml_printer > 0) => eval_expr(#, (LDB_LINUX) ? (new binding)->extend(Y_,value)->extend(X_,new (GC) double(tab)) : (new binding)->extend(X_,value)->extend(Y_,new (GC) double(tab)), true); | `v : v->variablep() && classp(v->name()) => { if (raw_data_p && ((raw_ref*)value)->oid()<=0) { fout << "NULL"; return; }; Expr tp = class_type(v->name()); Schema sch = type_to_schema(tp); list* names = sch->names(); list* rnames = names; set_current_object(); sm_ref p = (!raw_data_p) ? *((sm_ref*) value) : sm_ref(*((raw_ref*) value)); fout << v << "("; if (max_depth <= 0) rnames = primary_key(v->name()); int len = v->name()->length(); int offset = initial_offset; const char* data = p.deref(round_size(size_in_bytes(tp,true))); push_current_object(); for(Names nm = names; nm->consp(); nm=nm->tl) { Expr tp = sch->find(nm->hd); if (member(variable(nm->hd),rnames)) { fout << nm->hd << ": "; set_current_object(); print_value(tp,(void*)(data+round_size(offset)),tab+len+(nm->hd->length())+3, max_depth-1,true,fout); if (nm->tl->consp()) if (max_depth <= 0) fout << ", "; else { fout << ",\n"; spaces(tab+len+1,fout); }; }; offset = add_sizes(offset,size_in_bytes(tp,true)); }; pop_current_object(); if (max_depth <= 0) fout << "..."; fout << ")"; }; |`v : v->variablep() => #case get_declaration_binding(v->name()) | typedef(`tp,`tname) => print_value(tp,value,tab,max_depth,true,fout); | union(...r) => print_value(#,value,tab,max_depth,true,fout); | struct(...r) => print_value(#,value,tab,max_depth,true,fout); | _ => fout << "** Unknown Type: " << type << " **"; #end; | _ => fout << "** Unknown Type: " << type << " **"; #end; }; void plan::print_value ( void* value, short max_depth ) { short d = (max_depth<0) ? 0 : (max_depth>6) ? 6 : max_depth; push_current_object(); ::print_value(plan_type,value,0,d,false,cout); pop_current_object(); } void print_value ( const char* type, void* value, short max_depth) { push_current_object(); print_value(string_to_expr(new string(type)),value,0,max_depth,false,cout); pop_current_object(); cout << endl; };