hqlexpr.cpp 467 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include "build-config.h"
  15. #if defined(_DEBUG) && defined(_WIN32) && !defined(USING_MPATROL)
  16. #undef new
  17. #define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
  18. #endif
  19. #include "jlib.hpp"
  20. #include "jmisc.hpp"
  21. #include "jfile.hpp"
  22. #include "jiter.ipp"
  23. #include "jexcept.hpp"
  24. #include "jmutex.hpp"
  25. #include "junicode.hpp"
  26. #include "jutil.hpp"
  27. #include "hql.hpp"
  28. #include "hqlexpr.ipp"
  29. #include "hqlattr.hpp"
  30. #include "hqlgram.hpp"
  31. #include "hqlfold.hpp"
  32. #include "hqlthql.hpp"
  33. #include "hqlpmap.hpp"
  34. #include "hqlerrors.hpp"
  35. #include "hqlerror.hpp"
  36. #include "hqlplugins.hpp"
  37. #include "javahash.tpp"
  38. #include "hqltrans.ipp"
  39. #include "hqlutil.hpp"
  40. #include "hqlvalid.hpp"
  41. #include "hqlmeta.hpp"
  42. #include "workunit.hpp"
  43. #include "hqlrepository.hpp"
  44. #include "hqldesc.hpp"
  45. #include "hqlir.hpp"
  46. //This nearly works - but there are still some examples which have problems - primarily libraries, old parameter syntax, enums and other issues.
  47. //#define ANNOTATE_EXPR_POSITION
  48. #define ANNOTATE_DATASET_POSITION
  49. //#define NEW_VIRTUAL_DATASETS
  50. #define HQL_VERSION_NUMBER 30
  51. //#define ALL_MODULE_ATTRS_VIRTUAL
  52. //#define _REPORT_EXPRESSION_LEAKS
  53. //#define TRACE_THIS
  54. //#define CONSISTENCY_CHECK
  55. //#define GATHER_LINK_STATS
  56. //#define VERIFY_EXPR_INTEGRITY
  57. //#define CHECK_RECORD_CONSISTENCY
  58. // To debug a symbol in the C++ generated code, use SEARCH_NAME*
  59. // and set a breakpoint on debugMatchedName() below
  60. #ifdef _DEBUG
  61. //#define DEBUG_SCOPE
  62. //#define CHECK_RECORD_CONSISTENCY
  63. //#define PARANOID
  64. //#define SEARCH_NAME1 "v1"
  65. //#define SEARCH_NAME2 "v2"
  66. //#define CHECK_SELSEQ_CONSISTENCY
  67. //#define GATHER_COMMON_STATS
  68. #define VERIFY_EXPR_INTEGRITY
  69. #if defined(SEARCH_NAME1) || defined(SEARCH_NAME2)
  70. static void debugMatchedName() {}
  71. #endif
  72. #ifdef DEBUG_TRACK_INSTANCEID
  73. static int checkSeqId(unsigned __int64 seqid, unsigned why)
  74. {
  75. switch (seqid)
  76. {
  77. //Add a case statement here for each expression being tracked.
  78. case 0:
  79. break;
  80. default:
  81. return 0;
  82. }
  83. //Return values are here to allow breakpoints to be set - not because they are useful
  84. //Add breakpoint on the switch to break on all reasons.
  85. switch (why)
  86. {
  87. case 0: //Created
  88. return 1;
  89. case 1: // Linked
  90. return 2;
  91. case 2: // Released
  92. return 3;
  93. case 3: // Destroyed
  94. return 4;
  95. }
  96. return 0; // Unknown reason
  97. }
  98. #define CHECK_EXPR_SEQID(x) checkSeqId(seqid, x)
  99. #else
  100. #define CHECK_EXPR_SEQID(x)
  101. #endif
  102. #else
  103. #define CHECK_EXPR_SEQID(x)
  104. #endif
  105. #define STDIO_BUFFSIZE 0x10000 // 64K
  106. class HqlExprCache : public JavaHashTableOf<IHqlExpression>
  107. {
  108. public:
  109. HqlExprCache() : JavaHashTableOf<IHqlExpression>(false) {}
  110. protected:
  111. virtual bool matchesFindParam(const void * _element, const void * _key, unsigned fphash) const
  112. {
  113. const IHqlExpression * element = static_cast<const IHqlExpression *>(_element);
  114. const IHqlExpression * key = static_cast<const IHqlExpression *>(_key);
  115. return (element->getHash() == fphash) && element->equals(*key);
  116. }
  117. virtual unsigned getTableLimit(unsigned max)
  118. {
  119. return max/2;
  120. }
  121. };
  122. static Mutex * transformMutex;
  123. static CriticalSection * transformCS;
  124. static Semaphore * transformSemaphore;
  125. static HqlExprCache *exprCache;
  126. static CriticalSection * nullIntCS;
  127. static CriticalSection * unadornedCS;
  128. static CriticalSection * sourcePathCS;
  129. static ITypeInfo * nullType;
  130. static IValue * blank;
  131. static IHqlExpression * cachedActiveTableExpr;
  132. static IHqlExpression * cachedSelfExpr;
  133. static IHqlExpression * cachedSelfReferenceExpr;
  134. static IHqlExpression * cachedNoBody;
  135. static IHqlExpression * cachedNullRecord;
  136. static IHqlExpression * cachedNullRowRecord;
  137. static IHqlExpression * cachedOne;
  138. static IHqlExpression * cachedLocalAttribute;
  139. static IHqlExpression * constantTrue;
  140. static IHqlExpression * constantFalse;
  141. static IHqlExpression * defaultSelectorSequenceExpr;
  142. static IHqlExpression * newSelectAttrExpr;
  143. static IHqlExpression * recursiveExpr;
  144. static IHqlExpression * processingMarker;
  145. static IHqlExpression * mergePendingMarker;
  146. static IHqlExpression * mergeNoMatchMarker;
  147. static IHqlExpression * nullIntValue[9][2];
  148. static CriticalSection * exprCacheCS;
  149. static CriticalSection * crcCS;
  150. static KeptAtomTable * sourcePaths;
  151. #ifdef GATHER_COMMON_STATS
  152. static unsigned commonUpCount[no_last_pseudoop];
  153. static unsigned commonUpClash[no_last_pseudoop];
  154. static unsigned commonUpAnnCount[annotate_max];
  155. static unsigned commonUpAnnClash[annotate_max];
  156. #endif
  157. #ifdef GATHER_LINK_STATS
  158. static unsigned __int64 numLinks;
  159. static unsigned __int64 numReleases;
  160. static unsigned __int64 numCreateLinks;
  161. static unsigned __int64 numCreateReleases;
  162. static unsigned __int64 numTransformerLinks;
  163. static unsigned __int64 numTransformerReleases;
  164. static unsigned __int64 numSetExtra;
  165. static unsigned __int64 numSetExtraSame;
  166. static unsigned __int64 numSetExtraUnlinked;
  167. static unsigned numLocks;
  168. static unsigned numNestedLocks;
  169. static unsigned maxNestedLocks;
  170. static unsigned numNestedExtra;
  171. static unsigned insideCreate;
  172. #endif
  173. #ifdef _REPORT_EXPRESSION_LEAKS
  174. static char activeSource[256];
  175. void setActiveSource(const char * filename)
  176. {
  177. if (filename)
  178. {
  179. strncpy(activeSource, filename, sizeof(activeSource));
  180. activeSource[sizeof(activeSource)-1]= 0;
  181. }
  182. else
  183. activeSource[0] = 0;
  184. }
  185. #else
  186. void setActiveSource(const char * filename)
  187. {
  188. }
  189. #endif
  190. MODULE_INIT(INIT_PRIORITY_HQLINTERNAL)
  191. {
  192. transformMutex = new Mutex;
  193. transformCS = new CriticalSection;
  194. transformSemaphore = new Semaphore(NUM_PARALLEL_TRANSFORMS);
  195. exprCacheCS = new CriticalSection;
  196. crcCS = new CriticalSection;
  197. exprCache = new HqlExprCache;
  198. nullIntCS = new CriticalSection;
  199. unadornedCS = new CriticalSection;
  200. sourcePathCS = new CriticalSection;
  201. nullType = makeNullType();
  202. sourcePaths = new KeptAtomTable;
  203. blank = createStringValue("",(unsigned)0);
  204. cachedActiveTableExpr = createValue(no_activetable);
  205. cachedSelfExpr = createValue(no_self, makeRowType(NULL));
  206. cachedSelfReferenceExpr = createValue(no_selfref);
  207. cachedNullRecord = createRecord()->closeExpr();
  208. OwnedHqlExpr nonEmptyAttr = createAttribute(_nonEmpty_Atom);
  209. cachedNullRowRecord = createRecord(nonEmptyAttr);
  210. cachedOne = createConstant(1);
  211. cachedLocalAttribute = createAttribute(localAtom);
  212. constantTrue = createConstant(createBoolValue(true));
  213. constantFalse = createConstant(createBoolValue(false));
  214. defaultSelectorSequenceExpr = createAttribute(_selectorSequence_Atom);
  215. newSelectAttrExpr = createExprAttribute(newAtom);
  216. recursiveExpr = createAttribute(recursiveAtom);
  217. processingMarker = createValue(no_processing, makeNullType());
  218. mergePendingMarker = createValue(no_merge_pending, makeNullType());
  219. mergeNoMatchMarker = createValue(no_merge_nomatch, makeNullType());
  220. cachedNoBody = createValue(no_nobody, makeNullType());
  221. return true;
  222. }
  223. MODULE_EXIT()
  224. {
  225. for (unsigned i=0; i<=8; i++)
  226. {
  227. ::Release(nullIntValue[i][0]);
  228. ::Release(nullIntValue[i][1]);
  229. }
  230. cachedNoBody->Release();
  231. mergeNoMatchMarker->Release();
  232. mergePendingMarker->Release();
  233. processingMarker->Release();
  234. recursiveExpr->Release();
  235. newSelectAttrExpr->Release();
  236. defaultSelectorSequenceExpr->Release();
  237. constantFalse->Release();
  238. constantTrue->Release();
  239. blank->Release();
  240. cachedLocalAttribute->Release();
  241. cachedOne->Release();
  242. cachedActiveTableExpr->Release();
  243. cachedSelfReferenceExpr->Release();
  244. cachedSelfExpr->Release();
  245. cachedNullRowRecord->Release();
  246. cachedNullRecord->Release();
  247. nullType->Release();
  248. ClearTypeCache();
  249. #ifdef _REPORT_EXPRESSION_LEAKS
  250. if (exprCache->count())
  251. {
  252. #if 0 // Place debugging code inside here
  253. JavaHashIteratorOf<IHqlExpression> iter(*exprCache, false);
  254. ForEach(iter)
  255. {
  256. IHqlExpression & ret = iter.query();
  257. }
  258. #endif
  259. fprintf(stderr, "%s Hash table contains %d entries\n", activeSource, exprCache->count());
  260. }
  261. #endif
  262. ::Release(sourcePaths);
  263. delete sourcePathCS;
  264. delete unadornedCS;
  265. delete nullIntCS;
  266. exprCache->Release();
  267. delete exprCacheCS;
  268. delete crcCS;
  269. delete transformMutex;
  270. delete transformCS;
  271. delete transformSemaphore;
  272. }
  273. #ifdef GATHER_COMMON_STATS
  274. MODULE_INIT(INIT_PRIORITY_STANDARD)
  275. {
  276. return true;
  277. }
  278. MODULE_EXIT()
  279. {
  280. printf("op,cnt,clash");
  281. for (unsigned i=0; i < no_last_pseudoop; i++)
  282. {
  283. if (commonUpCount[i])
  284. printf("%s,%d,%d\n", getOpString((node_operator)i), commonUpCount[i], commonUpClash[i]);
  285. }
  286. for (unsigned j=0; j < annotate_max; j++)
  287. {
  288. if (commonUpAnnCount[j])
  289. printf("%d,%d,%d\n", j, commonUpAnnCount[j], commonUpAnnClash[j]);
  290. }
  291. fflush(stdout);
  292. }
  293. #endif
  294. #ifdef GATHER_LINK_STATS
  295. static void showStats()
  296. {
  297. printf("Links = %"I64F"d(%"I64F"d) releases = %"I64F"d(%"I64F"d)\n", numLinks, numTransformerLinks, numReleases, numTransformerReleases);
  298. printf("Create Links = %"I64F"d releases = %"I64F"d\n", numCreateLinks, numCreateReleases);
  299. printf("setExtra = %"I64F"d setExtraSame = %"I64F"d setExtraUnlinked = %"I64F"d\n", numSetExtra, numSetExtraSame, numSetExtraUnlinked);
  300. printf("numLocks = %d nestedLocks = %d maxNested=%d nestedLockExtra = %d\n", numLocks, numNestedLocks, maxNestedLocks, numNestedExtra);
  301. }
  302. MODULE_INIT(INIT_PRIORITY_STANDARD)
  303. {
  304. return true;
  305. }
  306. MODULE_EXIT()
  307. {
  308. showStats();
  309. }
  310. #endif
  311. extern HQL_API void clearCacheCounts()
  312. {
  313. #ifdef GATHER_COMMON_STATS
  314. _clear(commonUpCount);
  315. _clear(commonUpClash);
  316. _clear(commonUpAnnCount);
  317. _clear(commonUpAnnClash);
  318. #endif
  319. }
  320. static IHqlExpression * doCreateSelectExpr(HqlExprArray & args);
  321. //==============================================================================================================
  322. //createSourcePath actually uses a kept hash table at the moment, because the source filename is stored in
  323. //each attribute in the grammar, and the large number of links/releases have a noticeable effect (5%).
  324. //To release on demand sourcePaths should become an AtomTable, The link in the calls below should be deleted,
  325. //and sourcePath in ECLlocation needs to become linked.
  326. ISourcePath * createSourcePath(const char *value)
  327. {
  328. if (!value)
  329. return NULL;
  330. CriticalBlock crit(*sourcePathCS);
  331. return (ISourcePath *)LINK(sourcePaths->addAtom(value));
  332. }
  333. ISourcePath * createSourcePath(size32_t len, const char *value)
  334. {
  335. if (!value || !len)
  336. return NULL;
  337. char * nullTerminated = (char *)alloca(len+1);
  338. memcpy(nullTerminated, value, len);
  339. nullTerminated[len] = 0;
  340. CriticalBlock crit(*sourcePathCS);
  341. return (ISourcePath*)LINK(sourcePaths->addAtom(nullTerminated));
  342. }
  343. //==============================================================================================================
  344. bool HqlExprArray::containsBody(IHqlExpression & expr)
  345. {
  346. IHqlExpression * body = expr.queryBody();
  347. ForEachItem(i)
  348. {
  349. if (item(i).queryBody() == body)
  350. return true;
  351. }
  352. return false;
  353. }
  354. IHqlExpression * queryAttribute(IAtom * prop, const HqlExprArray & exprs)
  355. {
  356. ForEachItemIn(idx, exprs)
  357. {
  358. IHqlExpression & cur = (IHqlExpression &)exprs.item(idx);
  359. if (cur.isAttribute() && (cur.queryName() == prop))
  360. return &cur;
  361. }
  362. return NULL;
  363. }
  364. IHqlExpression * queryAttributeInList(IAtom * search, IHqlExpression * cur)
  365. {
  366. if (cur)
  367. {
  368. switch (cur->getOperator())
  369. {
  370. case no_attr:
  371. case no_attr_expr:
  372. case no_attr_link:
  373. if (cur->queryName() == search)
  374. return cur;
  375. break;
  376. case no_comma:
  377. IHqlExpression * match = queryAttributeInList(search, cur->queryChild(0));
  378. if (match)
  379. return match;
  380. return queryAttributeInList(search, cur->queryChild(1));
  381. }
  382. }
  383. return NULL;
  384. }
  385. IHqlExpression * queryOperatorInList(node_operator search, IHqlExpression * cur)
  386. {
  387. if (cur)
  388. {
  389. node_operator op = cur->getOperator();
  390. if (op == search)
  391. return cur;
  392. if (op != no_comma)
  393. return NULL;
  394. IHqlExpression * match = queryOperatorInList(search, cur->queryChild(0));
  395. if (match)
  396. return match;
  397. return queryOperatorInList(search, cur->queryChild(1));
  398. }
  399. return NULL;
  400. }
  401. extern HQL_API IHqlExpression * queryOperator(node_operator search, const HqlExprArray & args)
  402. {
  403. ForEachItemIn(i, args)
  404. {
  405. IHqlExpression & cur = args.item(i);
  406. if (cur.getOperator() == search)
  407. return &cur;
  408. }
  409. return NULL;
  410. }
  411. extern HQL_API IHqlExpression * queryAnnotation(IHqlExpression * expr, annotate_kind search)
  412. {
  413. loop
  414. {
  415. annotate_kind kind = expr->getAnnotationKind();
  416. if (kind == search)
  417. return expr;
  418. if (kind == annotate_none)
  419. return NULL;
  420. expr = expr->queryBody(true);
  421. }
  422. }
  423. extern HQL_API IHqlExpression * cloneAnnotationKind(IHqlExpression * donor, IHqlExpression * expr, annotate_kind search)
  424. {
  425. loop
  426. {
  427. annotate_kind kind = donor->getAnnotationKind();
  428. if (kind == annotate_none)
  429. return LINK(expr);
  430. IHqlExpression * donorBody = donor->queryBody(true);
  431. if (kind == search)
  432. {
  433. OwnedHqlExpr mapped = cloneAnnotationKind(donorBody, expr, search);
  434. return donor->cloneAnnotation(mapped);
  435. }
  436. donor = donorBody;
  437. }
  438. }
  439. extern HQL_API IHqlExpression * cloneInheritedAnnotations(IHqlExpression * donor, IHqlExpression * expr)
  440. {
  441. loop
  442. {
  443. annotate_kind kind = donor->getAnnotationKind();
  444. if (kind == annotate_none)
  445. return LINK(expr);
  446. IHqlExpression * donorBody = donor->queryBody(true);
  447. switch (kind)
  448. {
  449. case annotate_location:
  450. case annotate_meta:
  451. {
  452. OwnedHqlExpr mapped = cloneInheritedAnnotations(donorBody, expr);
  453. return donor->cloneAnnotation(mapped);
  454. }
  455. }
  456. donor = donorBody;
  457. }
  458. }
  459. IHqlExpression * cloneMissingAnnotations(IHqlExpression * donor, IHqlExpression * body)
  460. {
  461. annotate_kind kind = donor->getAnnotationKind();
  462. if (kind == annotate_none)
  463. return LINK(body);
  464. OwnedHqlExpr newbody = cloneMissingAnnotations(donor->queryBody(true), body);
  465. if (queryAnnotation(newbody, kind))
  466. return newbody.getClear();
  467. return donor->cloneAnnotation(newbody);
  468. }
  469. extern HQL_API IHqlExpression * forceCloneSymbol(IHqlExpression * donor, IHqlExpression * expr)
  470. {
  471. OwnedHqlExpr result = cloneAnnotationKind(donor, expr, annotate_symbol);
  472. assertex(expr != result);
  473. return result.getClear();
  474. }
  475. extern HQL_API IHqlExpression * cloneSymbol(IHqlExpression * donor, IIdAtom * newname, IHqlExpression * newbody, IHqlExpression * newfuncdef, HqlExprArray * operands)
  476. {
  477. assertex(donor->getAnnotationKind() == annotate_symbol);
  478. IHqlNamedAnnotation * annotation = static_cast<IHqlNamedAnnotation *>(donor->queryAnnotation());
  479. return annotation->cloneSymbol(newname, newbody, newfuncdef, operands);
  480. }
  481. extern HQL_API IHqlExpression * queryAnnotationAttribute(IAtom * search, IHqlExpression * annotation)
  482. {
  483. unsigned i=0;
  484. IHqlExpression * cur;
  485. while ((cur = annotation->queryAnnotationParameter(i++)) != NULL)
  486. {
  487. if (cur->queryName() == search && cur->isAttribute())
  488. return cur;
  489. }
  490. return NULL;
  491. }
  492. extern HQL_API IHqlExpression * queryMetaAttribute(IAtom * search, IHqlExpression * expr)
  493. {
  494. loop
  495. {
  496. annotate_kind kind = expr->getAnnotationKind();
  497. if (kind == annotate_none)
  498. return NULL;
  499. if (kind == annotate_meta)
  500. {
  501. IHqlExpression * cur = queryAnnotationAttribute(search, expr);
  502. if (cur)
  503. return cur;
  504. }
  505. expr = expr->queryBody(true);
  506. }
  507. }
  508. extern HQL_API void gatherMetaAttributes(HqlExprArray & matches, IAtom * search, IHqlExpression * expr)
  509. {
  510. loop
  511. {
  512. annotate_kind kind = expr->getAnnotationKind();
  513. if (kind == annotate_none)
  514. return;
  515. if (kind == annotate_meta)
  516. {
  517. unsigned i=0;
  518. IHqlExpression * cur;
  519. while ((cur = expr->queryAnnotationParameter(i++)) != NULL)
  520. {
  521. //It's possible we may want to implement this whole function as a member function and allow
  522. //information to be stored in a non expression format, and only create expressions when requested.
  523. //may end up less efficient in the end.
  524. if (cur->queryName() == search && cur->isAttribute())
  525. matches.append(*LINK(cur));
  526. }
  527. }
  528. expr = expr->queryBody(true);
  529. }
  530. }
  531. extern HQL_API void gatherAttributes(HqlExprArray & matches, IAtom * search, IHqlExpression * expr)
  532. {
  533. ForEachChild(i, expr)
  534. {
  535. IHqlExpression *kid = expr->queryChild(i);
  536. if (kid->isAttribute() && kid->queryName()==search)
  537. matches.append(*LINK(kid));
  538. }
  539. }
  540. extern HQL_API IHqlExpression * queryLocation(IHqlExpression * expr)
  541. {
  542. IHqlExpression * best = NULL;
  543. loop
  544. {
  545. annotate_kind kind = expr->getAnnotationKind();
  546. if (kind == annotate_none)
  547. return best;
  548. if (kind == annotate_location)
  549. return expr;
  550. best = expr;
  551. expr = expr->queryBody(true);
  552. }
  553. }
  554. extern HQL_API void gatherLocations(HqlExprCopyArray & matches, IHqlExpression * expr)
  555. {
  556. loop
  557. {
  558. annotate_kind kind = expr->getAnnotationKind();
  559. if (kind == annotate_none)
  560. return;
  561. if (kind == annotate_location || kind == annotate_symbol)
  562. matches.append(*expr);
  563. expr = expr->queryBody(true);
  564. }
  565. }
  566. extern HQL_API IHqlExpression * queryFunctionDefaults(IHqlExpression * expr)
  567. {
  568. return queryFunctionParameterDefaults(expr->queryType());
  569. }
  570. //==============================================================================================================
  571. static bool isSameText(IFileContents * text1, IFileContents * text2)
  572. {
  573. if (text1 == text2)
  574. return true;
  575. if (!text1 || !text2)
  576. return false;
  577. unsigned len1 = text1->length();
  578. if (len1 != text2->length())
  579. return false;
  580. return memcmp(text1->getText(), text2->getText(), len1) == 0;
  581. }
  582. void getFileContentText(StringBuffer & result, IFileContents * contents)
  583. {
  584. unsigned len = contents->length();
  585. const char * text = contents->getText();
  586. if ((len >= 3) && (memcmp(text, UTF8_BOM, 3) == 0))
  587. {
  588. len -= 3;
  589. text += 3;
  590. }
  591. result.append(len, text);
  592. }
  593. //---------------------------------------------------------------------------------------------------------------------
  594. void HqlParseContext::addForwardReference(IHqlScope * owner, IHasUnlinkedOwnerReference * child)
  595. {
  596. forwardLinks.append(*new ForwardScopeItem(owner, child));
  597. }
  598. IPropertyTree * HqlParseContext::queryEnsureArchiveModule(const char * name, IHqlScope * scope)
  599. {
  600. return ::queryEnsureArchiveModule(archive, name, scope);
  601. }
  602. void HqlParseContext::setGatherMeta(const MetaOptions & options)
  603. {
  604. metaOptions = options;
  605. metaState.gatherNow = !options.onlyGatherRoot;
  606. metaTree.setown(createPTree("Meta"));
  607. }
  608. static void setDefinitionText(IPropertyTree * target, const char * prop, IFileContents * contents)
  609. {
  610. StringBuffer sillyTempBuffer;
  611. getFileContentText(sillyTempBuffer, contents); // We can't rely on IFileContents->getText() being null terminated..
  612. target->setProp(prop, sillyTempBuffer);
  613. ISourcePath * sourcePath = contents->querySourcePath();
  614. target->setProp("@sourcePath", sourcePath->str());
  615. }
  616. void HqlParseContext::noteBeginAttribute(IHqlScope * scope, IFileContents * contents, IIdAtom * name)
  617. {
  618. if (queryArchive())
  619. {
  620. const char * moduleName = scope->queryFullName();
  621. IPropertyTree * module = queryEnsureArchiveModule(moduleName, scope);
  622. IPropertyTree * attr = queryArchiveAttribute(module, name->str());
  623. if (!attr)
  624. attr = createArchiveAttribute(module, name->str());
  625. setDefinitionText(attr, "", contents);
  626. }
  627. if (checkBeginMeta())
  628. {
  629. ISourcePath * sourcePath = contents->querySourcePath();
  630. IPropertyTree * attr = metaTree->addPropTree("Source", createPTree("Source"));
  631. setFullNameProp(attr, "@name", scope->queryFullName(), name->str());
  632. attr->setProp("@sourcePath", sourcePath->str());
  633. metaState.nesting.append(attr);
  634. }
  635. if (globalDependTree)
  636. {
  637. IPropertyTree * attr = globalDependTree->addPropTree("Attribute", createPTree("Attribute"));
  638. attr->setProp("@module", scope->queryFullName());
  639. attr->setProp("@name", name->str());
  640. //attr->setPropInt("@flags", symbol->getObType()); MORE
  641. }
  642. }
  643. void HqlParseContext::noteBeginQuery(IHqlScope * scope, IFileContents * contents)
  644. {
  645. if (queryArchive())
  646. {
  647. const char * moduleName = scope->queryFullName();
  648. if (moduleName && *moduleName)
  649. {
  650. IPropertyTree * module = queryEnsureArchiveModule(moduleName, scope);
  651. setDefinitionText(module, "Text", contents);
  652. }
  653. }
  654. if (checkBeginMeta())
  655. {
  656. ISourcePath * sourcePath = contents->querySourcePath();
  657. IPropertyTree * attr = metaTree->addPropTree("Query", createPTree("Query"));
  658. attr->setProp("@sourcePath", sourcePath->str());
  659. metaState.nesting.append(attr);
  660. }
  661. }
  662. void HqlParseContext::noteBeginModule(IHqlScope * scope, IFileContents * contents)
  663. {
  664. if (queryArchive())
  665. {
  666. const char * moduleName = scope->queryFullName();
  667. if (moduleName && *moduleName)
  668. {
  669. IPropertyTree * module = queryEnsureArchiveModule(moduleName, scope);
  670. setDefinitionText(module, "Text", contents);
  671. }
  672. }
  673. if (checkBeginMeta())
  674. {
  675. ISourcePath * sourcePath = contents->querySourcePath();
  676. IPropertyTree * attr = metaTree->addPropTree("Source", createPTree("Source"));
  677. attr->setProp("@sourcePath", sourcePath->str());
  678. metaState.nesting.append(attr);
  679. }
  680. }
  681. void HqlParseContext::noteEndAttribute()
  682. {
  683. if (checkEndMeta())
  684. finishMeta();
  685. }
  686. void HqlParseContext::noteEndQuery()
  687. {
  688. if (checkEndMeta())
  689. finishMeta();
  690. }
  691. void HqlParseContext::noteEndModule()
  692. {
  693. if (checkEndMeta())
  694. finishMeta();
  695. }
  696. void HqlParseContext::noteFinishedParse(IHqlScope * scope)
  697. {
  698. if (metaState.gatherNow)
  699. expandScopeSymbolsMeta(metaState.nesting.tos(), scope);
  700. }
  701. void HqlParseContext::notePrivateSymbols(IHqlScope * scope)
  702. {
  703. if (metaState.gatherNow)
  704. expandScopeSymbolsMeta(metaState.nesting.tos(), scope);
  705. }
  706. bool HqlParseContext::checkBeginMeta()
  707. {
  708. if (!metaTree)
  709. return false;
  710. if (!metaOptions.onlyGatherRoot)
  711. return true;
  712. metaState.gatherNow = (metaState.nesting.ordinality() == 0);
  713. return metaState.gatherNow;
  714. }
  715. bool HqlParseContext::checkEndMeta()
  716. {
  717. if (!metaTree)
  718. return false;
  719. if (!metaOptions.onlyGatherRoot)
  720. return true;
  721. bool wasGathering = metaState.gatherNow;
  722. metaState.gatherNow = (metaState.nesting.ordinality() == 2);
  723. return wasGathering;
  724. }
  725. void HqlParseContext::finishMeta()
  726. {
  727. metaState.nesting.pop();
  728. }
  729. //---------------------------------------------------------------------------------------------------------------------
  730. extern HQL_API IPropertyTree * createAttributeArchive()
  731. {
  732. Owned<IPropertyTree> archive = createPTree("Archive");
  733. archive->setProp("@build", BUILD_TAG);
  734. archive->setProp("@eclVersion", LANGUAGE_VERSION);
  735. return archive.getClear();
  736. }
  737. IPropertyTree * queryEnsureArchiveModule(IPropertyTree * archive, const char * name, IHqlScope * scope)
  738. {
  739. //MORE: Move this into a member of the parse context to also handle dependencies.
  740. StringBuffer lowerName;
  741. lowerName.append(name).toLowerCase();
  742. StringBuffer xpath,s;
  743. xpath.append("Module[@key=\"").append(lowerName).append("\"]");
  744. IPropertyTree * module = archive->queryPropTree(xpath);
  745. if (!module)
  746. {
  747. module = archive->addPropTree("Module", createPTree());
  748. module->setProp("@name", name ? name : "");
  749. module->setProp("@key", lowerName);
  750. if (scope)
  751. {
  752. unsigned flagsToSave = (scope->getPropInt(flagsAtom, 0) & PLUGIN_SAVEMASK);
  753. if (flagsToSave)
  754. module->setPropInt("@flags", flagsToSave);
  755. scope->getProp(pluginAtom, s.clear());
  756. if (s.length())
  757. {
  758. module->setProp("@fullname", s.str());
  759. StringBuffer pluginName(s.str());
  760. getFileNameOnly(pluginName, false);
  761. module->setProp("@plugin", pluginName.str());
  762. }
  763. scope->getProp(versionAtom, s.clear());
  764. if (s.length())
  765. module->setProp("@version", s.str());
  766. }
  767. }
  768. return module;
  769. }
  770. extern HQL_API IPropertyTree * queryArchiveAttribute(IPropertyTree * module, const char * name)
  771. {
  772. StringBuffer lowerName, xpath;
  773. lowerName.append(name).toLowerCase();
  774. xpath.append("Attribute[@key=\"").append(lowerName).append("\"]");
  775. return module->queryPropTree(xpath);
  776. }
  777. extern HQL_API IPropertyTree * createArchiveAttribute(IPropertyTree * module, const char * name)
  778. {
  779. StringBuffer lowerName;
  780. lowerName.append(name).toLowerCase();
  781. IPropertyTree * attr = module->addPropTree("Attribute", createPTree());
  782. attr->setProp("@name", name);
  783. attr->setProp("@key", lowerName);
  784. return attr;
  785. }
  786. //---------------------------------------------------------------------------------------------------------------------
  787. void HqlLookupContext::noteBeginAttribute(IHqlScope * scope, IFileContents * contents, IIdAtom * name)
  788. {
  789. if (queryNestedDependTree())
  790. createDependencyEntry(scope, name);
  791. parseCtx.noteBeginAttribute(scope, contents, name);
  792. }
  793. void HqlLookupContext::noteBeginQuery(IHqlScope * scope, IFileContents * contents)
  794. {
  795. parseCtx.noteBeginQuery(scope, contents);
  796. }
  797. void HqlLookupContext::noteBeginModule(IHqlScope * scope, IFileContents * contents)
  798. {
  799. parseCtx.noteBeginModule(scope, contents);
  800. }
  801. void HqlLookupContext::noteExternalLookup(IHqlScope * parentScope, IHqlExpression * expr)
  802. {
  803. if (queryArchive())
  804. {
  805. node_operator op = expr->getOperator();
  806. if ((op == no_remotescope) || (op == no_mergedscope))
  807. {
  808. //Ensure the archive contains entries for each module - even if nothing is accessed from it
  809. //It would be preferrable to only check once, but adds very little time anyway.
  810. IHqlScope * resolvedScope = expr->queryScope();
  811. parseCtx.queryEnsureArchiveModule(resolvedScope->queryFullName(), resolvedScope);
  812. }
  813. }
  814. if (curAttrTree && !dependents.contains(*expr))
  815. {
  816. node_operator op = expr->getOperator();
  817. if ((op != no_remotescope) && (op != no_mergedscope))
  818. {
  819. dependents.append(*expr);
  820. const char * moduleName = parentScope->queryFullName();
  821. if (moduleName)
  822. {
  823. IPropertyTree * depend = curAttrTree->addPropTree("Depend", createPTree());
  824. depend->setProp("@module", moduleName);
  825. depend->setProp("@name", expr->queryName()->str());
  826. }
  827. }
  828. }
  829. }
  830. void HqlLookupContext::createDependencyEntry(IHqlScope * parentScope, IIdAtom * id)
  831. {
  832. const char * moduleName = parentScope->queryFullName();
  833. const char * nameText = id->lower()->str();
  834. StringBuffer xpath;
  835. xpath.append("Attr[@module=\"").append(moduleName).append("\"][@name=\"").append(nameText).append("\"]");
  836. IPropertyTree * attr = queryNestedDependTree()->queryPropTree(xpath.str());
  837. if (!attr)
  838. {
  839. attr = queryNestedDependTree()->addPropTree("Attr", createPTree());
  840. attr->setProp("@module", moduleName);
  841. attr->setProp("@name", nameText);
  842. }
  843. curAttrTree.set(attr);
  844. }
  845. //---------------------------------------------------------------------------------------------------------------------
  846. const char *getOpString(node_operator op)
  847. {
  848. switch(op)
  849. {
  850. case no_band: return "&";
  851. case no_bor: return "|";
  852. case no_bxor: return " BXOR ";
  853. case no_mul: return "*";
  854. case no_div: return "/";
  855. case no_modulus: return "%";
  856. case no_exp: return "EXP";
  857. case no_round: return "ROUND";
  858. case no_roundup: return "ROUNDUP";
  859. case no_truncate: return "ROUNDDOWN";
  860. case no_power: return "POWER";
  861. case no_ln: return "LN";
  862. case no_sin: return "SIN";
  863. case no_cos: return "COS";
  864. case no_tan: return "TAN";
  865. case no_asin: return "ASIN";
  866. case no_acos: return "ACOS";
  867. case no_atan: return "ATAN";
  868. case no_atan2: return "ATAN2";
  869. case no_sinh: return "SINH";
  870. case no_cosh: return "COSH";
  871. case no_tanh: return "TANH";
  872. case no_log10: return "LOG";
  873. case no_sqrt: return "SQRT";
  874. case no_negate: return "-";
  875. case no_sub: return " - ";
  876. case no_add: return " + ";
  877. case no_addfiles: return " + ";
  878. case no_merge: return "MERGE";
  879. case no_concat: return " | ";
  880. case no_eq: return "=";
  881. case no_ne: return "<>";
  882. case no_lt: return "<";
  883. case no_le: return "<=";
  884. case no_gt: return ">";
  885. case no_ge: return ">=";
  886. case no_order: return "<=>";
  887. case no_unicodeorder: return "UNICODEORDER";
  888. case no_not: return "NOT ";
  889. case no_and: return " AND ";
  890. case no_or: return " OR ";
  891. case no_xor: return " XOR ";
  892. case no_notin: return " NOT IN ";
  893. case no_in: return " IN ";
  894. case no_indict: return " IN ";
  895. case no_notbetween: return " NOT BETWEEN ";
  896. case no_between: return " BETWEEN ";
  897. case no_comma: return ",";
  898. case no_compound: return ",";
  899. case no_count: case no_countlist: case no_countdict: return "COUNT";
  900. case no_counter: return "COUNTER";
  901. case no_countgroup: return "COUNT";
  902. case no_distribution: return "DISTRIBUTION";
  903. case no_max: case no_maxgroup: case no_maxlist: return "MAX";
  904. case no_min: case no_mingroup: case no_minlist: return "MIN";
  905. case no_sum: case no_sumgroup: case no_sumlist: return "SUM";
  906. case no_ave: case no_avegroup: return "AVG";
  907. case no_variance: case no_vargroup: return "VARIANCE";
  908. case no_covariance: case no_covargroup: return "COVARIANCE";
  909. case no_correlation: case no_corrgroup: return "CORRELATION";
  910. case no_map: return "MAP";
  911. case no_if: return "IF";
  912. case no_mapto: return "=>";
  913. case no_constant: return "<constant>";
  914. case no_field: return "<field>";
  915. case no_exists: case no_existslist: case no_existsdict: return "EXISTS";
  916. case no_existsgroup: return "EXISTS";
  917. case no_select: return ".";
  918. case no_table: return "DATASET";
  919. case no_temptable: return "<temptable>";
  920. case no_workunit_dataset: return "<workunit_dataset>";
  921. case no_scope: return "MODULE";
  922. case no_remotescope: return "<scope>";
  923. case no_mergedscope: return "<scope>";
  924. case no_privatescope: return "<private_scope>";
  925. case no_list: return "<list>";
  926. case no_selectmap: return "SELECT_MAP";
  927. case no_selectnth: return "SELECT_NTH";
  928. case no_filter: return "FILTER";
  929. case no_param: return "<parameter>";
  930. case no_within: return "WITHIN ";
  931. case no_notwithin: return "NOT WITHIN ";
  932. case no_index: return "<index>";
  933. case no_all: return "ALL";
  934. case no_left: return "LEFT";
  935. case no_right: return "RIGHT";
  936. case no_outofline: return "OUTOFLINE";
  937. case no_dedup: return "DEDUP";
  938. case no_enth: return "ENTH";
  939. case no_sample: return "SAMPLE";
  940. case no_sort: return "SORT";
  941. case no_subsort: return "SUBSORT";
  942. case no_sorted: return "SORTED";
  943. case no_choosen: return "CHOOSEN";
  944. case no_choosesets: return "CHOOSESETS";
  945. case no_buildindex: return "BUILDINDEX";
  946. case no_output: return "OUTPUT";
  947. case no_record: return "RECORD";
  948. case no_fetch: return "FETCH";
  949. case no_compound_fetch: return "compoundfetch";
  950. case no_join: return "JOIN";
  951. case no_selfjoin: return "JOIN";
  952. case no_newusertable: return "NEWTABLE";
  953. case no_usertable: return "TABLE";
  954. case no_aggregate: return "AGGREGATE";
  955. case no_which: return "WHICH";
  956. case no_case: return "CASE";
  957. case no_choose: return "CHOOSE";
  958. case no_rejected: return "REJECTED";
  959. case no_evaluate: return "EVALUATE";
  960. case no_cast: return "CAST";
  961. case no_implicitcast: return "<implicit-cast>";
  962. case no_external: return "<external>";
  963. case no_externalcall: return "<external call>";
  964. case no_macro: return "<macro>";
  965. case no_failure: return "FAILURE";
  966. case no_success: return "SUCCESS";
  967. case no_recovery: return "RECOVERY";
  968. case no_sql: return "SQL";
  969. case no_flat: return "FLAT";
  970. case no_csv: return "CSV";
  971. case no_xml: return "XML";
  972. case no_when: return "WHEN";
  973. case no_priority: return "PRIORITY";
  974. case no_rollup: return "ROLLUP";
  975. case no_iterate: return "ITERATE";
  976. case no_assign: return ":=";
  977. case no_asstring: return "ASSTRING";
  978. case no_assignall: return "ASSIGNALL";
  979. case no_update: return "update";
  980. case no_alias: return "alias";
  981. case no_denormalize: return "DENORMALIZE";
  982. case no_denormalizegroup: return "DENORMALIZE";
  983. case no_normalize: return "NORMALIZE";
  984. case no_group: return "GROUP";
  985. case no_grouped: return "GROUPED";
  986. case no_unknown: return "unknown";
  987. case no_any: return "any";
  988. case no_is_null: return "ISNULL";
  989. case no_is_valid: return "ISVALID";
  990. case no_abs: return "ABS";
  991. case no_substring: return "substring";
  992. case no_newaggregate: return "TABLE";
  993. case no_trim: return "trim";
  994. case no_realformat: return "REALFORMAT";
  995. case no_intformat: return "INTFORMAT";
  996. case no_regex_find: return "REGEXFIND";
  997. case no_regex_replace: return "REGEXREPLACE";
  998. case no_current_date: return "current_date";
  999. case no_current_time: return "current_time";
  1000. case no_current_timestamp: return "current time stamp";
  1001. case no_cogroup: return "COGROUP";
  1002. case no_cosort: return "COSORT";
  1003. case no_sortlist: return "SORTBY";
  1004. case no_recordlist: return "[]";
  1005. case no_transformlist: return "[]";
  1006. case no_transformebcdic: return "EBCDIC";
  1007. case no_transformascii: return "ASCII";
  1008. case no_hqlproject: return "PROJECT";
  1009. case no_dataset_from_transform: return "DATASET";
  1010. case no_newtransform: return "NEWTRANSFORM";
  1011. case no_transform: return "TRANSFORM";
  1012. case no_attr: return "no_attr";
  1013. case no_attr_expr: return "no_attr_expr";
  1014. case no_attr_link: return "no_attr_link";
  1015. case no_self: return "SELF";
  1016. case no_selfref: return "SELF";
  1017. case no_thor: return "THOR";
  1018. case no_distribute: return "DISTRIBUTE";
  1019. case no_distributed: return "DISTRIBUTED";
  1020. case no_keyeddistribute: return "DISTRIBUTE";
  1021. case no_rank: return "RANK";
  1022. case no_ranked: return "RANKED";
  1023. case no_ordered: return "no_ordered";
  1024. case no_hash: return "HASH";
  1025. case no_hash32: return "HASH32";
  1026. case no_hash64: return "HASH64";
  1027. case no_hashmd5: return "HASHMD5";
  1028. case no_none: return "no_none";
  1029. case no_notnot: return "no_notnot";
  1030. case no_range: return "no_range";
  1031. case no_rangeto: return "no_rangeto";
  1032. case no_rangefrom: return "no_rangefrom";
  1033. case no_service: return "no_service";
  1034. case no_mix: return "no_mix";
  1035. case no_funcdef: return "no_funcdef";
  1036. case no_wait: return "no_wait";
  1037. case no_notify: return "no_notify";
  1038. case no_event: return "no_event";
  1039. case no_persist: return "PERSIST";
  1040. case no_omitted: return "no_omitted";
  1041. case no_setconditioncode: return "no_setconditioncode";
  1042. case no_selectfields: return "no_selectfields";
  1043. case no_quoted: return "no_quoted";
  1044. case no_variable: return "no_variable";
  1045. case no_bnot: return "no_bnot";
  1046. case no_charlen: return "LENGTH";
  1047. case no_sizeof: return "SIZEOF";
  1048. case no_offsetof: return "OFFSETOF";
  1049. case no_postinc: return "no_postinc";
  1050. case no_postdec: return "no_postdec";
  1051. case no_preinc: return "no_preinc";
  1052. case no_predec: return "no_predec";
  1053. case no_pselect: return "no_pselect";
  1054. case no_address: return "no_address";
  1055. case no_deref: return "no_deref";
  1056. case no_nullptr: return "NULL";
  1057. case no_decimalstack: return "no_decimalstack";
  1058. case no_typetransfer: return "TRANSFER";
  1059. case no_apply: return "APPLY";
  1060. case no_pipe: return "PIPE";
  1061. case no_cloned: return "no_cloned";
  1062. case no_cachealias: return "no_cachealias";
  1063. case no_joined: return "JOINED";
  1064. case no_lshift: return "<<";
  1065. case no_rshift: return ">>";
  1066. case no_colon: return ":";
  1067. case no_global: return "GLOBAL";
  1068. case no_stored: return "STORED";
  1069. case no_checkpoint: return "checkpoint";
  1070. case no_compound_indexread: return "compound_indexread";
  1071. case no_compound_diskread: return "compound_diskread";
  1072. case no_translated: return "no_translated";
  1073. case no_ifblock: return "IFBLOCK";
  1074. case no_crc: return "HASHCRC";
  1075. case no_random: return "RANDOM";
  1076. case no_childdataset: return "no_childdataset";
  1077. case no_envsymbol: return "no_envsymbol";
  1078. case no_null: return "[]";
  1079. case no_ensureresult: return "ensureresult";
  1080. case no_getresult: return "getresult";
  1081. case no_setresult: return "setresult";
  1082. case no_extractresult: return "extractresult";
  1083. case no_type: return "TYPE";
  1084. case no_position: return "no_position";
  1085. case no_bound_func: return "no_bound_func";
  1086. case no_bound_type: return "no_bound_type";
  1087. case no_hint: return "no_hint";
  1088. case no_metaactivity: return "no_metaactivity";
  1089. case no_loadxml: return "no_loadxml";
  1090. case no_fieldmap: return "no_fieldmap";
  1091. case no_template_context: return "no_template_context";
  1092. case no_nofold: return "NOFOLD";
  1093. case no_nohoist: return "NOHOIST";
  1094. case no_fail: return "FAIL";
  1095. case no_filepos: return "no_filepos";
  1096. case no_file_logicalname: return "no_file_logicalname";
  1097. case no_alias_project: return "no_alias_project";
  1098. case no_alias_scope: return "no_alias_scope";
  1099. case no_sequential: return "SEQUENTIAL";
  1100. case no_parallel: return "PARALLEL";
  1101. case no_actionlist: return "no_actionlist";
  1102. case no_nolink: return "no_link";
  1103. case no_workflow: return "no_workflow";
  1104. case no_workflow_action: return "no_workflow_action";
  1105. case no_failcode: return "FAILCODE";
  1106. case no_failmessage: return "FAILMESSAGE";
  1107. case no_eventname: return "EVENTNAME";
  1108. case no_eventextra: return "EVENTEXTRA";
  1109. case no_independent: return "INDEPENDENT";
  1110. case no_keyindex: return "INDEX";
  1111. case no_newkeyindex: return "INDEX";
  1112. case no_keyed: return "KEYED";
  1113. case no_split: return "SPLIT";
  1114. case no_subgraph: return "no_subgraph";
  1115. case no_dependenton: return "no_dependenton";
  1116. case no_spill: return "SPILL";
  1117. case no_setmeta: return "no_setmeta";
  1118. case no_throughaggregate: return "no_throughaggregate";
  1119. case no_joincount: return "JOINCOUNT";
  1120. case no_countcompare: return "no_countcompare";
  1121. case no_limit: return "LIMIT";
  1122. case no_fromunicode: return "FROMUNICODE";
  1123. case no_tounicode: return "TOUNICODE";
  1124. case no_keyunicode: return "KEYUNICODE";
  1125. case no_parse: return "PARSE";
  1126. case no_newparse: return "PARSE";
  1127. case no_skip: return "SKIP";
  1128. case no_matched: return "MATCHED";
  1129. case no_matchtext: return "MATCHTEXT";
  1130. case no_matchlength: return "MATCHLENGTH";
  1131. case no_matchposition: return "MATCHPOSITION";
  1132. case no_matchunicode: return "MATCHUNICODE";
  1133. case no_matchrow: return "MATCHROW";
  1134. case no_matchutf8: return "MATCHUTF8";
  1135. case no_pat_select: return "/";
  1136. case no_pat_index: return "[]";
  1137. case no_pat_const: return "no_pat_const";
  1138. case no_pat_pattern: return "PATTERN";
  1139. case no_pat_follow: return "no_pat_follow";
  1140. case no_pat_first: return "FIRST";
  1141. case no_pat_last: return "LAST";
  1142. case no_pat_repeat: return "REPEAT";
  1143. case no_pat_instance: return "no_pat_instance";
  1144. case no_pat_anychar: return "ANY";
  1145. case no_pat_token: return "TOKEN";
  1146. case no_pat_imptoken: return "no_imp_token";
  1147. case no_pat_set: return "no_pat_set";
  1148. case no_pat_checkin: return "IN";
  1149. case no_pat_x_before_y: return "BEFORE";
  1150. case no_pat_x_after_y: return "AFTER";
  1151. case no_pat_before_y: return "ASSERT BEFORE";
  1152. case no_pat_after_y: return "ASSERT AFTER";
  1153. case no_pat_beginpattern: return "no_pat_beginpattern";
  1154. case no_pat_endpattern: return "no_pat_endpattern";
  1155. case no_pat_checklength: return "LENGTH";
  1156. case no_pat_use: return "USE";
  1157. case no_pat_validate: return "VALIDATE";
  1158. case no_topn: return "TOPN";
  1159. case no_outputscalar: return "OUTPUT";
  1160. case no_penalty: return "PENALTY";
  1161. case no_rowdiff: return "ROWDIFF";
  1162. case no_wuid: return "WUID";
  1163. case no_featuretype: return "no_featuretype";
  1164. case no_pat_guard: return "GUARD";
  1165. case no_xmltext: return "XMLTEXT";
  1166. case no_xmlunicode: return "XMLUNICODE";
  1167. case no_xmlproject: return "XMLPROJECT";
  1168. case no_newxmlparse: return "PARSE";
  1169. case no_xmlparse: return "PARSE";
  1170. case no_xmldecode: return "XMLDECODE";
  1171. case no_xmlencode: return "XMLENCODE";
  1172. case no_pat_featureparam: return "no_pat_featureparam";
  1173. case no_pat_featureactual: return "no_pat_featureactual";
  1174. case no_pat_featuredef: return "no_pat_featuredef";
  1175. case no_evalonce: return "no_evalonce";
  1176. case no_distributer: return "DISTRIBUTE";
  1177. case no_impure: return "<impure>";
  1178. case no_addsets: return "+";
  1179. case no_rowvalue: return "no_rowvalue";
  1180. case no_pat_case: return "CASE";
  1181. case no_pat_nocase: return "NOCASE";
  1182. case no_evaluate_stmt: return "EVALUATE";
  1183. case no_return_stmt: return "RETURN";
  1184. case no_activetable: return "<Active>";
  1185. case no_preload: return "PRELOAD";
  1186. case no_createset: return "SET";
  1187. case no_assertkeyed: return "KEYED";
  1188. case no_assertwild: return "WILD";
  1189. case no_httpcall: return "HTTPCALL";
  1190. case no_soapcall: return "SOAPCALL";
  1191. case no_soapcall_ds: return "SOAPCALL";
  1192. case no_newsoapcall: return "SOAPCALL";
  1193. case no_newsoapcall_ds: return "SOAPCALL";
  1194. case no_soapaction_ds: return "SOAPCALL";
  1195. case no_newsoapaction_ds: return "SOAPCALL";
  1196. case no_temprow: return "ROW";
  1197. case no_projectrow: return "ROW";
  1198. case no_createrow: return "ROW";
  1199. case no_activerow: return "<ActiveRow>";
  1200. case no_newrow: return "<NewRow>";
  1201. case no_catch: return "CATCH";
  1202. case no_reference: return "no_reference";
  1203. case no_callback: return "no_callback";
  1204. case no_keyedlimit: return "LIMIT";
  1205. case no_keydiff: return "KEYDIFF";
  1206. case no_keypatch: return "KEYPATCH";
  1207. case no_returnresult: return "no_returnresult";
  1208. case no_id2blob: return "no_id2blob";
  1209. case no_blob2id: return "no_blob2id";
  1210. case no_anon: return "no_anon";
  1211. case no_embedbody: return "no_embedbody";
  1212. case no_sortpartition: return "no_sortpartition";
  1213. case no_define: return "DEFINE";
  1214. case no_globalscope: return "GLOBAL";
  1215. case no_forcelocal: return "LOCAL";
  1216. case no_typedef: return "typedef";
  1217. case no_matchattr: return "no_matchattr";
  1218. case no_pat_production: return "no_pat_production";
  1219. case no_guard: return "no_guard";
  1220. case no_datasetfromrow: return "DATASET";
  1221. case no_assertconstant: return "no_assertconstant";
  1222. case no_clustersize: return "no_clustersize";
  1223. case no_compound_disknormalize: return "no_compound_disknormalize";
  1224. case no_compound_diskaggregate: return "no_compound_diskaggregate";
  1225. case no_compound_diskcount: return "no_compound_diskcount";
  1226. case no_compound_diskgroupaggregate: return "no_compound_diskgroupaggregate";
  1227. case no_compound_indexnormalize: return "no_compound_indexnormalize";
  1228. case no_compound_indexaggregate: return "no_compound_indexaggregate";
  1229. case no_compound_indexcount: return "no_compound_indexcount";
  1230. case no_compound_indexgroupaggregate: return "no_compound_indexgroupaggregate";
  1231. case no_compound_childread: return "no_compound_childread";
  1232. case no_compound_childnormalize: return "no_compound_childnormalize";
  1233. case no_compound_childaggregate: return "no_compound_childaggregate";
  1234. case no_compound_childcount: return "no_compound_childcount";
  1235. case no_compound_childgroupaggregate: return "no_compound_childgroupaggregate";
  1236. case no_compound_selectnew: return "no_compound_selectnew";
  1237. case no_compound_inline: return "no_compound_inline";
  1238. case no_setworkflow_cond: return "no_setworkflow_cond";
  1239. case no_nothor: return "NOTHOR";
  1240. case no_call: return "no_call";
  1241. case no_getgraphresult: return "GetGraphResult";
  1242. case no_setgraphresult: return "SetGraphResult";
  1243. case no_assert: return "ASSERT";
  1244. case no_assert_ds: return "ASSERT";
  1245. case no_namedactual: return "no_namedactual";
  1246. case no_combine: return "COMBINE";
  1247. case no_combinegroup: return "COMBINE";
  1248. case no_rows: return "ROWS";
  1249. case no_rollupgroup: return "ROLLUP";
  1250. case no_regroup: return "REGGROUP";
  1251. case no_inlinetable: return "DATASET";
  1252. case no_spillgraphresult: return "spillgraphresult";
  1253. case no_enum: return "ENUM";
  1254. case no_pat_or: return "|";
  1255. case no_loop: return "LOOP";
  1256. case no_loopbody: return "no_loopbody";
  1257. case no_cluster: return "CLUSTER";
  1258. case no_forcenolocal: return "NOLOCAL";
  1259. case no_allnodes: return "ALLNODES";
  1260. case no_last_op: return "no_last_op";
  1261. case no_pat_compound: return "no_pat_compound";
  1262. case no_pat_begintoken: return "no_pat_begintoken";
  1263. case no_pat_endtoken: return "no_pat_endtoken";
  1264. case no_pat_begincheck: return "no_pat_begincheck";
  1265. case no_pat_endcheckin: return "no_pat_endcheckin";
  1266. case no_pat_endchecklength: return "no_pat_endchecklength";
  1267. case no_pat_beginseparator: return "no_pat_beginseparator";
  1268. case no_pat_endseparator: return "no_pat_endseparator";
  1269. case no_pat_separator: return "no_pat_separator";
  1270. case no_pat_beginvalidate: return "no_pat_beginvalidate";
  1271. case no_pat_endvalidate: return "no_pat_endvalidate";
  1272. case no_pat_dfa: return "no_pat_dfa";
  1273. case no_pat_singlechar: return "no_pat_singlechar";
  1274. case no_pat_beginrecursive: return "no_pat_beginrecursive";
  1275. case no_pat_endrecursive: return "no_pat_endrecursive";
  1276. case no_pat_utf8single: return "no_pat_utf8single";
  1277. case no_pat_utf8lead: return "no_pat_utf8lead";
  1278. case no_pat_utf8follow: return "no_pat_utf8follow";
  1279. case no_sequence: return "__SEQUENCE__";
  1280. case no_forwardscope: return "MODULE";
  1281. case no_virtualscope: return "MODULE";
  1282. case no_concretescope: return "MODULE";
  1283. case no_purevirtual: return "__PURE__";
  1284. case no_internalselect: return "no_internalselect";
  1285. case no_delayedselect: return "no_delayedselect";
  1286. // case no_func: return "no_func";
  1287. case no_libraryselect: return "no_libraryselect";
  1288. case no_libraryscope: return "MODULE";
  1289. case no_libraryscopeinstance: return "MODULE";
  1290. case no_libraryinput: return "LibraryInput";
  1291. case no_process: return "PROCESS";
  1292. case no_thisnode: return "THISNODE";
  1293. case no_graphloop: return "GRAPH";
  1294. case no_rowset: return "ROWSET";
  1295. case no_loopcounter: return "COUNTER";
  1296. case no_getgraphloopresult: return "GraphLoopResult";
  1297. case no_setgraphloopresult: return "ReturnGraphLoopResult";
  1298. case no_rowsetindex: return "no_rowsetindex";
  1299. case no_rowsetrange: return "RANGE";
  1300. case no_assertstepped: return "STEPPED";
  1301. case no_assertsorted: return "SORTED";
  1302. case no_assertgrouped: return "GROUPED";
  1303. case no_assertdistributed: return "DISTRIBUTED";
  1304. case no_datasetlist: return "<dataset-list>";
  1305. case no_mergejoin: return "MERGEJOIN";
  1306. case no_nwayjoin: return "JOIN";
  1307. case no_nwaymerge: return "MERGE";
  1308. case no_stepped: return "STEPPED";
  1309. case no_getgraphloopresultset: return "N-way GraphLoopResult";
  1310. case no_attrname: return "name";
  1311. case no_nonempty: return "NONEMPTY";
  1312. case no_filtergroup: return "HAVING";
  1313. case no_rangecommon: return "no_rangecommon";
  1314. case no_section: return "SECTION";
  1315. case no_nobody: return "NOBODY";
  1316. case no_deserialize: return "no_deserialize";
  1317. case no_serialize: return "no_serialize";
  1318. case no_eclcrc: return "ECLCRC";
  1319. case no_pure: return "<pure>";
  1320. case no_pseudods: return "<pseudods>";
  1321. case no_top: return "TOP";
  1322. case no_uncommoned_comma: return ",";
  1323. case no_nameof: return "__NAMEOF__";
  1324. case no_processing: return "no_processing";
  1325. case no_merge_pending: return "no_merge_pending";
  1326. case no_merge_nomatch: return "no_merge_nomatch";
  1327. case no_toxml: return "TOXML";
  1328. case no_catchds: return "CATCH";
  1329. case no_readspill: return "no_readspill";
  1330. case no_writespill: return "no_writespill";
  1331. case no_commonspill: return "no_commonspill";
  1332. case no_forcegraph: return "GRAPH";
  1333. case no_sectioninput: return "no_sectioninput";
  1334. case no_related: return "no_related";
  1335. case no_definesideeffect: return "no_definessideeffect";
  1336. case no_executewhen: return "WHEN";
  1337. case no_callsideeffect: return "no_callsideeffect";
  1338. case no_fromxml: return "FROMXML";
  1339. case no_preservemeta: return "order-tracking";
  1340. case no_normalizegroup: return "NORMALIZE";
  1341. case no_indirect: return "no_indirect";
  1342. case no_selectindirect: return ".<>";
  1343. case no_isomitted: return "no_isomitted";
  1344. case no_getenv: return "GETENV";
  1345. case no_once: return "ONCE";
  1346. case no_persist_check: return "no_persist_check";
  1347. case no_create_initializer: return "no_create_initializer";
  1348. case no_owned_ds: return "no_owned_ds";
  1349. case no_complex: return ",";
  1350. case no_assign_addfiles: return "+=";
  1351. case no_debug_option_value: return "__DEBUG__";
  1352. case no_dataset_alias: return "TABLE";
  1353. case no_childquery: return "no_childquery";
  1354. case no_createdictionary: return "DICTIONARY";
  1355. case no_chooseds: return "CHOOSE";
  1356. case no_datasetfromdictionary: return "DATASET";
  1357. case no_delayedscope: return "no_delayedscope";
  1358. case no_assertconcrete: return "no_assertconcrete";
  1359. case no_unboundselect: return "no_unboundselect";
  1360. case no_id: return "no_id";
  1361. case no_orderedactionlist: return "ORDERED";
  1362. case no_unused6:
  1363. case no_unused13: case no_unused14: case no_unused15:
  1364. case no_unused25: case no_unused28: case no_unused29:
  1365. case no_unused30: case no_unused31: case no_unused32: case no_unused33: case no_unused34: case no_unused35: case no_unused36: case no_unused37: case no_unused38:
  1366. case no_unused40: case no_unused41: case no_unused42: case no_unused43: case no_unused44: case no_unused45: case no_unused46: case no_unused47: case no_unused48: case no_unused49:
  1367. case no_unused50: case no_unused52:
  1368. case no_unused80:
  1369. case no_unused81:
  1370. case no_unused83:
  1371. case no_unused101:
  1372. case no_unused102:
  1373. return "unused";
  1374. /* if fail, use "hqltest -internal" to find out why. */
  1375. default: assertex(false); return "???";
  1376. }
  1377. }
  1378. node_operator getReverseOp(node_operator op)
  1379. {
  1380. switch (op)
  1381. {
  1382. case no_lt: return no_gt;
  1383. case no_gt: return no_lt;
  1384. case no_le: return no_ge;
  1385. case no_ge: return no_le;
  1386. case no_eq:
  1387. case no_ne:
  1388. return op;
  1389. default:
  1390. assertex(!"Should not be called");
  1391. }
  1392. return op;
  1393. }
  1394. node_operator getInverseOp(node_operator op)
  1395. {
  1396. switch (op)
  1397. {
  1398. case no_not: return no_notnot;
  1399. case no_notnot: return no_not;
  1400. case no_eq: return no_ne;
  1401. case no_ne: return no_eq;
  1402. case no_lt: return no_ge;
  1403. case no_le: return no_gt;
  1404. case no_gt: return no_le;
  1405. case no_ge: return no_lt;
  1406. case no_notin: return no_in;
  1407. case no_in: return no_notin;
  1408. case no_notbetween: return no_between;
  1409. case no_between: return no_notbetween;
  1410. // case no_notwithin: return no_within;
  1411. // case no_within: return no_notwithin;
  1412. default:
  1413. return no_none;
  1414. }
  1415. }
  1416. bool checkConstant(node_operator op)
  1417. {
  1418. switch (op)
  1419. {
  1420. case no_field:
  1421. case no_externalcall: // not constant because we may not be able to load the dll + fold it.
  1422. case no_external:
  1423. case no_select:
  1424. case no_stored:
  1425. case no_persist:
  1426. case no_checkpoint:
  1427. case no_once:
  1428. case no_getresult:
  1429. case no_getgraphresult:
  1430. case no_getgraphloopresult:
  1431. case no_variable:
  1432. case no_httpcall:
  1433. case no_soapcall:
  1434. case no_soapcall_ds:
  1435. case no_soapaction_ds:
  1436. case no_newsoapcall:
  1437. case no_newsoapcall_ds:
  1438. case no_newsoapaction_ds:
  1439. case no_filepos:
  1440. case no_file_logicalname:
  1441. case no_failcode:
  1442. case no_failmessage:
  1443. case no_eventname:
  1444. case no_eventextra:
  1445. case no_skip:
  1446. case no_assert:
  1447. case no_assert_ds:
  1448. case no_fail:
  1449. case no_left:
  1450. case no_right:
  1451. case no_sizeof:
  1452. case no_offsetof:
  1453. case no_xmltext:
  1454. case no_xmlunicode:
  1455. case no_xmlproject:
  1456. case no_matched:
  1457. case no_matchtext:
  1458. case no_matchunicode:
  1459. case no_matchlength:
  1460. case no_matchposition:
  1461. case no_matchrow:
  1462. case no_matchutf8:
  1463. case no_when:
  1464. case no_priority:
  1465. case no_event:
  1466. case no_independent:
  1467. case no_embedbody:
  1468. case no_translated:
  1469. case no_assertkeyed: // not sure about this - might be better to implement in the constant folder
  1470. case no_assertstepped:
  1471. case no_colon:
  1472. case no_globalscope:
  1473. case no_param:
  1474. case no_matchattr:
  1475. case no_keyindex:
  1476. case no_newkeyindex:
  1477. case no_joined:
  1478. case no_activerow:
  1479. case no_newrow:
  1480. case no_output:
  1481. case no_pat_featuredef:
  1482. case no_assertwild:
  1483. case no_call:
  1484. case no_cluster:
  1485. case no_forcenolocal:
  1486. case no_allnodes:
  1487. case no_thisnode:
  1488. case no_internalselect:
  1489. case no_purevirtual:
  1490. case no_libraryinput:
  1491. case no_libraryselect:
  1492. case no_rowsetindex:
  1493. case no_rowsetrange:
  1494. case no_counter:
  1495. case no_loopcounter:
  1496. case no_sequence:
  1497. case no_table:
  1498. return false;
  1499. // following are currently not implemented in the const folder - can enable if they are.
  1500. case no_global:
  1501. case no_rank:
  1502. case no_ranked:
  1503. case no_typetransfer:
  1504. case no_hash:
  1505. case no_hash32:
  1506. case no_hash64:
  1507. case no_hashmd5:
  1508. case no_crc:
  1509. case no_is_valid:
  1510. case no_is_null:
  1511. case no_xmldecode:
  1512. case no_xmlencode:
  1513. case no_sortpartition:
  1514. case no_clustersize:
  1515. return false;
  1516. }
  1517. return true;
  1518. }
  1519. int getPrecedence(node_operator op)
  1520. {
  1521. switch (op)
  1522. {
  1523. case no_field:
  1524. case no_constant:
  1525. case no_null:
  1526. return 12;
  1527. case no_pat_select:
  1528. return 11;
  1529. case no_substring:
  1530. return 10;
  1531. case no_negate:
  1532. case no_cast:
  1533. case no_implicitcast: // GH->RKC- Need to check child?
  1534. return 9;
  1535. case no_mul:
  1536. case no_div:
  1537. case no_modulus:
  1538. return 8;
  1539. case no_concat:
  1540. case no_add:
  1541. case no_sub:
  1542. return 7;
  1543. case no_lshift:
  1544. case no_rshift:
  1545. return 6;
  1546. case no_band:
  1547. case no_bor:
  1548. case no_bxor:
  1549. return 5;
  1550. case no_between:
  1551. case no_notbetween:
  1552. case no_in:
  1553. case no_notin:
  1554. case no_indict:
  1555. case no_comma:
  1556. case no_compound:
  1557. case no_eq:
  1558. case no_ne:
  1559. case no_lt:
  1560. case no_le:
  1561. case no_gt:
  1562. case no_ge:
  1563. case no_within:
  1564. case no_notwithin:
  1565. return 4;
  1566. case no_not:
  1567. case no_pat_follow:
  1568. return 3;
  1569. case no_and:
  1570. return 2;
  1571. case no_pat_or:
  1572. case no_or:
  1573. case no_xor:
  1574. return 1;
  1575. case no_abs:
  1576. case no_mapto:
  1577. case no_which:
  1578. case no_choose:
  1579. case no_rejected:
  1580. case no_exp:
  1581. case no_round:
  1582. case no_roundup:
  1583. case no_truncate:
  1584. case no_power:
  1585. case no_ln:
  1586. case no_sin:
  1587. case no_cos:
  1588. case no_tan:
  1589. case no_asin:
  1590. case no_acos:
  1591. case no_atan:
  1592. case no_atan2:
  1593. case no_sinh:
  1594. case no_cosh:
  1595. case no_tanh:
  1596. case no_log10:
  1597. case no_sqrt:
  1598. case NO_AGGREGATEGROUP:
  1599. case no_trim:
  1600. case no_intformat:
  1601. case no_realformat:
  1602. case no_regex_find:
  1603. case no_regex_replace:
  1604. case no_fromunicode:
  1605. case no_tounicode:
  1606. case no_keyunicode:
  1607. case no_toxml:
  1608. return 0;
  1609. case no_compound_indexread:
  1610. case no_compound_diskread:
  1611. case no_compound_disknormalize:
  1612. case no_compound_diskaggregate:
  1613. case no_compound_diskcount:
  1614. case no_compound_diskgroupaggregate:
  1615. case no_compound_indexnormalize:
  1616. case no_compound_indexaggregate:
  1617. case no_compound_indexcount:
  1618. case no_compound_indexgroupaggregate:
  1619. case no_compound_childread:
  1620. case no_compound_childnormalize:
  1621. case no_compound_childaggregate:
  1622. case no_compound_childcount:
  1623. case no_compound_childgroupaggregate:
  1624. case no_compound_inline:
  1625. case no_filter:
  1626. case no_limit:
  1627. case no_catchds:
  1628. case no_distribution:
  1629. case NO_AGGREGATE:
  1630. case no_keyedlimit:
  1631. case no_keydiff:
  1632. case no_keypatch:
  1633. return -1;
  1634. default:
  1635. return 11;
  1636. }
  1637. }
  1638. childDatasetType getChildDatasetType(IHqlExpression * expr)
  1639. {
  1640. switch (expr->getOperator())
  1641. {
  1642. case no_none:
  1643. case no_null:
  1644. case no_anon:
  1645. case no_pseudods:
  1646. case no_all:
  1647. case no_table:
  1648. case no_temptable:
  1649. case no_inlinetable:
  1650. case no_xmlproject:
  1651. case no_workunit_dataset:
  1652. case no_field:
  1653. case no_left:
  1654. case no_right:
  1655. case no_self:
  1656. case no_top:
  1657. case no_keyindex:
  1658. case no_newkeyindex:
  1659. case no_getresult:
  1660. case no_getgraphresult:
  1661. case no_getgraphloopresult:
  1662. case no_comma:
  1663. case no_compound:
  1664. case no_fail:
  1665. case no_skip:
  1666. case no_activetable:
  1667. case no_httpcall:
  1668. case no_soapcall:
  1669. case no_newsoapcall:
  1670. case no_externalcall: // None in the sense it is generally used for.
  1671. case no_alias:
  1672. case no_id2blob:
  1673. case no_embedbody:
  1674. case no_datasetfromrow:
  1675. case no_datasetfromdictionary:
  1676. case no_createrow:
  1677. case no_param:
  1678. case no_typetransfer:
  1679. case no_translated:
  1680. case no_call:
  1681. case no_rows:
  1682. case no_external:
  1683. case no_delayedselect:
  1684. case no_libraryselect:
  1685. case no_internalselect:
  1686. case no_unboundselect:
  1687. case no_purevirtual:
  1688. case no_libraryinput:
  1689. case no_rowsetindex:
  1690. case no_rowsetrange:
  1691. case no_definesideeffect:
  1692. case no_callsideeffect:
  1693. case no_fromxml:
  1694. case no_dataset_from_transform:
  1695. return childdataset_none;
  1696. case no_group:
  1697. case no_grouped:
  1698. case no_distribute:
  1699. case no_distributed:
  1700. case no_cosort:
  1701. case no_keyed:
  1702. case no_sort:
  1703. case no_subsort:
  1704. case no_sorted:
  1705. case no_stepped:
  1706. case no_transformebcdic:
  1707. case no_transformascii:
  1708. case no_selectfields:
  1709. case no_newaggregate:
  1710. case no_newusertable:
  1711. case no_usertable:
  1712. case no_alias_project:
  1713. case no_cachealias:
  1714. case no_choosen:
  1715. case no_choosesets:
  1716. case no_enth:
  1717. case no_filter:
  1718. case no_sample:
  1719. case no_compound_indexread:
  1720. case no_compound_diskread:
  1721. case no_compound_disknormalize:
  1722. case no_compound_diskaggregate:
  1723. case no_compound_diskcount:
  1724. case no_compound_diskgroupaggregate:
  1725. case no_compound_indexnormalize:
  1726. case no_compound_indexaggregate:
  1727. case no_compound_indexcount:
  1728. case no_compound_indexgroupaggregate:
  1729. case no_compound_childread:
  1730. case no_compound_childnormalize:
  1731. case no_compound_childaggregate:
  1732. case no_compound_childcount:
  1733. case no_compound_childgroupaggregate:
  1734. case no_compound_selectnew:
  1735. case no_compound_inline:
  1736. case no_metaactivity:
  1737. case no_throughaggregate:
  1738. case no_countcompare:
  1739. case no_fieldmap:
  1740. case NO_AGGREGATE:
  1741. case no_output:
  1742. case no_buildindex:
  1743. case no_apply:
  1744. case no_distribution:
  1745. case no_within:
  1746. case no_notwithin:
  1747. case no_parse:
  1748. case no_xmlparse:
  1749. case no_compound_fetch:
  1750. case no_topn:
  1751. case no_distributer:
  1752. case no_createset:
  1753. case no_keypatch:
  1754. case no_assert_ds:
  1755. case no_assertsorted:
  1756. case no_assertgrouped:
  1757. case no_assertdistributed:
  1758. case no_extractresult:
  1759. return childdataset_dataset;
  1760. case no_keyedlimit:
  1761. case no_preload:
  1762. case no_limit:
  1763. case no_catchds:
  1764. case no_forcegraph:
  1765. case no_owned_ds:
  1766. case no_dataset_alias:
  1767. case no_split:
  1768. case no_spill:
  1769. case no_activerow:
  1770. case no_alias_scope:
  1771. case no_executewhen: //second argument is independent of the other arguments
  1772. case no_selectnth:
  1773. case no_readspill:
  1774. case no_commonspill:
  1775. case no_writespill:
  1776. case no_newrow:
  1777. case no_returnresult:
  1778. case no_setgraphresult:
  1779. case no_setgraphloopresult:
  1780. case no_spillgraphresult:
  1781. return childdataset_dataset_noscope;
  1782. case no_setresult:
  1783. case no_sizeof:
  1784. case no_offsetof:
  1785. case no_nameof:
  1786. case no_blob2id:
  1787. case no_subgraph:
  1788. case no_deserialize:
  1789. case no_serialize:
  1790. if (expr->queryChild(0)->isDataset())
  1791. return childdataset_dataset_noscope;
  1792. return childdataset_none;
  1793. case no_pipe:
  1794. if (expr->queryChild(0)->isDataset())
  1795. return childdataset_dataset;
  1796. return childdataset_none;
  1797. case no_cloned:
  1798. case no_colon:
  1799. case no_globalscope:
  1800. case no_nofold:
  1801. case no_nohoist:
  1802. case no_section:
  1803. case no_thor:
  1804. case no_catch:
  1805. case no_forcelocal:
  1806. case no_nothor:
  1807. case no_cluster:
  1808. case no_forcenolocal:
  1809. case no_allnodes:
  1810. case no_thisnode:
  1811. case no_sectioninput:
  1812. case no_outofline:
  1813. if (expr->isDataset())
  1814. return childdataset_dataset_noscope;
  1815. return childdataset_none;
  1816. case no_ensureresult:
  1817. return childdataset_dataset_noscope;
  1818. case no_preservemeta:
  1819. //Only has a single dataset - but fields are referenced via active selector, so use the many option
  1820. return childdataset_many;
  1821. case no_newxmlparse:
  1822. case no_newparse:
  1823. case no_soapcall_ds:
  1824. case no_soapaction_ds:
  1825. case no_newsoapcall_ds:
  1826. case no_newsoapaction_ds:
  1827. return childdataset_datasetleft;
  1828. case no_keyeddistribute:
  1829. return childdataset_leftright;
  1830. case no_select:
  1831. if (expr->hasAttribute(newAtom) && expr->isDataset())
  1832. return childdataset_dataset;
  1833. return childdataset_none;
  1834. case no_sub:
  1835. return expr->isDataset() ? childdataset_many_noscope : childdataset_none;
  1836. case no_if:
  1837. return expr->isDataset() ? childdataset_if : childdataset_none;
  1838. case no_map:
  1839. return expr->isDataset() ? childdataset_map : childdataset_none;
  1840. case no_case:
  1841. return expr->isDataset() ? childdataset_case : childdataset_none;
  1842. case no_normalize:
  1843. if (expr->queryChild(1)->isDataset())
  1844. return childdataset_leftright;
  1845. return childdataset_left;
  1846. case no_chooseds:
  1847. return childdataset_many_noscope;
  1848. case no_merge:
  1849. case no_regroup:
  1850. case no_cogroup:
  1851. return childdataset_many; //NB: sorted() attribute on merge uses no_activetable as the selector, not the left dataset
  1852. case no_nonempty:
  1853. case no_datasetlist:
  1854. case no_addfiles:
  1855. case no_keydiff:
  1856. case no_related:
  1857. return childdataset_many_noscope; // two arbitrary inputs
  1858. case no_hqlproject:
  1859. case no_projectrow:
  1860. case no_loop:
  1861. case no_graphloop:
  1862. case no_filtergroup:
  1863. case no_normalizegroup:
  1864. case no_rollupgroup:
  1865. return childdataset_left;
  1866. case no_denormalize:
  1867. case no_denormalizegroup:
  1868. case no_fetch:
  1869. case no_join:
  1870. case no_joincount:
  1871. case no_combine:
  1872. case no_combinegroup: // Hmm really LEFT,rows but that's a bit too nasty. RIGHT can be the first rhs record
  1873. case no_process:
  1874. case no_aggregate:
  1875. return childdataset_leftright;
  1876. case no_mergejoin:
  1877. case no_nwayjoin:
  1878. case no_nwaymerge:
  1879. return childdataset_nway_left_right;
  1880. case no_selfjoin:
  1881. return childdataset_same_left_right;
  1882. case no_dedup:
  1883. case no_rollup:
  1884. return childdataset_top_left_right;
  1885. case no_iterate:
  1886. return childdataset_same_left_right;
  1887. case no_update:
  1888. return childdataset_left;
  1889. case no_evaluate:
  1890. return childdataset_evaluate;
  1891. case no_mapto:
  1892. case no_funcdef:
  1893. case no_template_context:
  1894. case no_variable:
  1895. case no_quoted:
  1896. case no_reference:
  1897. case no_pselect:
  1898. return childdataset_none; // a lie.
  1899. default:
  1900. if (!expr->isDataset() || hasReferenceModifier(expr->queryType()))
  1901. return childdataset_none;
  1902. assertex(!"Need to implement getChildDatasetType() for dataset operator");
  1903. break;
  1904. }
  1905. return childdataset_none;
  1906. }
  1907. inline unsigned doGetNumChildTables(IHqlExpression * dataset)
  1908. {
  1909. switch (dataset->getOperator())
  1910. {
  1911. case no_sub:
  1912. if (dataset->isDataset())
  1913. return 2;
  1914. return 0;
  1915. case no_merge:
  1916. case no_regroup:
  1917. case no_datasetlist:
  1918. case no_nonempty:
  1919. case no_cogroup:
  1920. case no_chooseds:
  1921. {
  1922. unsigned ret = 0;
  1923. ForEachChild(idx, dataset)
  1924. {
  1925. if (dataset->queryChild(idx)->isDataset())
  1926. ret++;
  1927. }
  1928. return ret;
  1929. }
  1930. case no_addfiles:
  1931. case no_denormalize:
  1932. case no_denormalizegroup:
  1933. case no_join:
  1934. case no_fetch:
  1935. case no_joincount:
  1936. case no_keyeddistribute:
  1937. case no_keydiff:
  1938. case no_combine:
  1939. case no_combinegroup:
  1940. case no_process:
  1941. case no_related:
  1942. return 2;
  1943. case no_mergejoin:
  1944. case no_nwayjoin:
  1945. case no_nwaymerge:
  1946. return 0; //??
  1947. case no_selfjoin:
  1948. case no_alias_project:
  1949. case no_alias_scope:
  1950. case no_newaggregate:
  1951. case no_apply:
  1952. case no_cachealias:
  1953. case no_choosen:
  1954. case no_choosesets:
  1955. case no_cosort:
  1956. case no_dedup:
  1957. case no_distribute:
  1958. case no_distributed:
  1959. case no_preservemeta:
  1960. case no_enth:
  1961. case no_filter:
  1962. case no_group:
  1963. case no_grouped:
  1964. case no_iterate:
  1965. case no_keyed:
  1966. case no_metaactivity:
  1967. case no_hqlproject:
  1968. case no_rollup:
  1969. case no_sample:
  1970. case no_selectnth:
  1971. case no_sort:
  1972. case no_subsort:
  1973. case no_sorted:
  1974. case no_stepped:
  1975. case no_assertsorted:
  1976. case no_assertgrouped:
  1977. case no_assertdistributed:
  1978. case no_selectfields:
  1979. case no_compound_indexread:
  1980. case no_compound_diskread:
  1981. case no_compound_disknormalize:
  1982. case no_compound_diskaggregate:
  1983. case no_compound_diskcount:
  1984. case no_compound_diskgroupaggregate:
  1985. case no_compound_indexnormalize:
  1986. case no_compound_indexaggregate:
  1987. case no_compound_indexcount:
  1988. case no_compound_indexgroupaggregate:
  1989. case no_compound_childread:
  1990. case no_compound_childnormalize:
  1991. case no_compound_childaggregate:
  1992. case no_compound_childcount:
  1993. case no_compound_childgroupaggregate:
  1994. case no_compound_selectnew:
  1995. case no_compound_inline:
  1996. case no_transformascii:
  1997. case no_transformebcdic:
  1998. case no_newusertable:
  1999. case no_aggregate:
  2000. case no_usertable:
  2001. case NO_AGGREGATE:
  2002. case no_output:
  2003. case no_buildindex:
  2004. case no_distribution:
  2005. case no_split:
  2006. case no_spill:
  2007. case no_commonspill:
  2008. case no_readspill:
  2009. case no_writespill:
  2010. case no_throughaggregate:
  2011. case no_countcompare:
  2012. case no_within:
  2013. case no_notwithin:
  2014. case no_limit:
  2015. case no_catchds:
  2016. case no_fieldmap:
  2017. case no_parse:
  2018. case no_xmlparse:
  2019. case no_newparse:
  2020. case no_newxmlparse:
  2021. case no_compound_fetch:
  2022. case no_topn:
  2023. case no_distributer:
  2024. case no_preload:
  2025. case no_createset:
  2026. case no_soapcall_ds:
  2027. case no_soapaction_ds:
  2028. case no_newsoapcall_ds:
  2029. case no_newsoapaction_ds:
  2030. case no_activerow:
  2031. case no_newrow:
  2032. case no_keyedlimit:
  2033. case no_keypatch:
  2034. case no_returnresult:
  2035. case no_setgraphresult:
  2036. case no_setgraphloopresult:
  2037. case no_projectrow:
  2038. case no_assert_ds:
  2039. case no_rollupgroup:
  2040. case no_spillgraphresult:
  2041. case no_loop:
  2042. case no_graphloop:
  2043. case no_extractresult:
  2044. case no_filtergroup:
  2045. case no_forcegraph:
  2046. case no_executewhen:
  2047. case no_normalizegroup:
  2048. case no_owned_ds:
  2049. case no_dataset_alias:
  2050. case no_ensureresult:
  2051. return 1;
  2052. case no_deserialize:
  2053. case no_serialize:
  2054. if (dataset->queryChild(0)->isDataset())
  2055. return 1;
  2056. return 0;
  2057. case no_childdataset:
  2058. case no_left:
  2059. case no_right:
  2060. case no_self:
  2061. case no_top:
  2062. case no_temptable:
  2063. case no_inlinetable:
  2064. case no_xmlproject:
  2065. case no_table:
  2066. case no_workunit_dataset:
  2067. case no_field:
  2068. case no_none:
  2069. case no_funcdef:
  2070. case no_null:
  2071. case no_anon:
  2072. case no_pseudods:
  2073. case no_all:
  2074. case no_keyindex:
  2075. case no_newkeyindex:
  2076. case no_getresult:
  2077. case no_getgraphresult:
  2078. case no_getgraphloopresult:
  2079. case no_fail:
  2080. case no_skip:
  2081. case no_activetable:
  2082. case no_httpcall:
  2083. case no_soapcall:
  2084. case no_newsoapcall:
  2085. case no_externalcall: // None in the sense it is generally used for.
  2086. case no_alias:
  2087. case no_id2blob:
  2088. case no_embedbody:
  2089. case no_datasetfromrow:
  2090. case no_datasetfromdictionary:
  2091. case no_param:
  2092. case no_translated:
  2093. case no_call:
  2094. case no_rows:
  2095. case no_external:
  2096. case no_rowsetindex:
  2097. case no_rowsetrange:
  2098. case no_definesideeffect:
  2099. case no_callsideeffect:
  2100. case no_fromxml:
  2101. case no_dataset_from_transform:
  2102. return 0;
  2103. case no_delayedselect:
  2104. case no_unboundselect:
  2105. case no_libraryselect:
  2106. case no_internalselect:
  2107. case no_purevirtual:
  2108. case no_libraryinput:
  2109. return 0;
  2110. case no_subgraph:
  2111. case no_sizeof:
  2112. case no_offsetof:
  2113. case no_nameof:
  2114. case no_blob2id:
  2115. case no_setresult:
  2116. if (dataset->queryChild(0)->isDataset())
  2117. return 1;
  2118. return 0;
  2119. case no_select:
  2120. if (dataset->hasAttribute(newAtom) && dataset->isDataset())
  2121. return 1;
  2122. return 0;
  2123. case no_normalize:
  2124. if (dataset->queryChild(1)->isDataset())
  2125. return 2;
  2126. return 1;
  2127. case no_cloned:
  2128. case no_colon:
  2129. case no_globalscope:
  2130. case no_nofold:
  2131. case no_nohoist:
  2132. case no_section:
  2133. case no_thor:
  2134. case no_pipe:
  2135. case no_catch:
  2136. case no_forcelocal:
  2137. case no_nothor:
  2138. case no_cluster:
  2139. case no_forcenolocal:
  2140. case no_allnodes:
  2141. case no_thisnode:
  2142. case no_sectioninput:
  2143. case no_outofline:
  2144. if (dataset->isDataset())
  2145. return 1;
  2146. return 0;
  2147. case no_if:
  2148. case no_case:
  2149. case no_map:
  2150. //assertex(!"Error: IF getNumChildTables() needs special processing");
  2151. return 0;
  2152. case no_sequential:
  2153. case no_parallel:
  2154. case no_orderedactionlist:
  2155. return 0;
  2156. case no_quoted:
  2157. case no_variable:
  2158. return 0;
  2159. case no_mapto:
  2160. case no_compound:
  2161. return 0; // a lie.
  2162. default:
  2163. if (!dataset->isDataset())
  2164. return 0;
  2165. PrintLogExprTree(dataset, "missing operator: ");
  2166. assertex(false);
  2167. return 0;
  2168. }
  2169. }
  2170. unsigned getNumChildTables(IHqlExpression * dataset)
  2171. {
  2172. unsigned num = doGetNumChildTables(dataset);
  2173. #ifdef _DEBUG
  2174. switch (getChildDatasetType(dataset))
  2175. {
  2176. case childdataset_none:
  2177. case childdataset_nway_left_right:
  2178. assertex(num==0);
  2179. break;
  2180. case childdataset_dataset:
  2181. case childdataset_datasetleft:
  2182. case childdataset_left:
  2183. case childdataset_same_left_right:
  2184. case childdataset_top_left_right:
  2185. case childdataset_dataset_noscope:
  2186. assertex(num==1);
  2187. break;
  2188. case childdataset_leftright:
  2189. if (dataset->getOperator() != no_aggregate)
  2190. assertex(num==2);
  2191. break;
  2192. case childdataset_many_noscope:
  2193. case childdataset_many:
  2194. break;
  2195. case childdataset_if:
  2196. case childdataset_case:
  2197. case childdataset_map:
  2198. assertex(num==0);
  2199. break;
  2200. case childdataset_evaluate:
  2201. assertex(num==1);
  2202. break;
  2203. default:
  2204. UNIMPLEMENTED;
  2205. }
  2206. #endif
  2207. return num;
  2208. }
  2209. node_operator queryHasRows(IHqlExpression * expr)
  2210. {
  2211. switch (expr->getOperator())
  2212. {
  2213. case no_denormalizegroup:
  2214. case no_combinegroup:
  2215. case no_aggregate:
  2216. return no_right;
  2217. case no_loop:
  2218. case no_graphloop:
  2219. case no_rollupgroup:
  2220. case no_nwayjoin:
  2221. case no_filtergroup:
  2222. case no_mergejoin:
  2223. return no_left;
  2224. }
  2225. #ifdef _DEBUG
  2226. //This would imply a missing entry above....
  2227. assertex(!expr->queryAttribute(_rowsid_Atom));
  2228. #endif
  2229. return no_none;
  2230. }
  2231. bool definesColumnList(IHqlExpression * dataset)
  2232. {
  2233. node_operator op = dataset->getOperator();
  2234. switch (op)
  2235. {
  2236. case no_merge: // MORE - is this right?
  2237. case no_addfiles:
  2238. case no_regroup:
  2239. case no_nonempty:
  2240. return true; // a fake
  2241. case no_alias_project:
  2242. case no_alias_scope:
  2243. case no_sub:
  2244. case no_cachealias:
  2245. case no_choosen:
  2246. case no_choosesets:
  2247. case no_cloned:
  2248. case no_cosort:
  2249. case no_dedup:
  2250. case no_distribute:
  2251. case no_distributed:
  2252. case no_preservemeta:
  2253. case no_enth:
  2254. case no_filter:
  2255. case no_group:
  2256. case no_grouped:
  2257. case no_keyed:
  2258. case no_metaactivity:
  2259. case no_nofold:
  2260. case no_nohoist:
  2261. case no_section:
  2262. case no_sample:
  2263. case no_sort:
  2264. case no_subsort:
  2265. case no_sorted:
  2266. case no_stepped:
  2267. case no_assertsorted:
  2268. case no_assertgrouped:
  2269. case no_assertdistributed:
  2270. case no_thor:
  2271. case no_compound_indexread:
  2272. case no_compound_diskread:
  2273. case no_compound_disknormalize:
  2274. case no_compound_diskaggregate:
  2275. case no_compound_diskcount:
  2276. case no_compound_diskgroupaggregate:
  2277. case no_compound_indexnormalize:
  2278. case no_compound_indexaggregate:
  2279. case no_compound_indexcount:
  2280. case no_compound_indexgroupaggregate:
  2281. case no_compound_childread:
  2282. case no_compound_childnormalize:
  2283. case no_compound_childaggregate:
  2284. case no_compound_childcount:
  2285. case no_compound_childgroupaggregate:
  2286. case no_compound_selectnew:
  2287. case no_compound_inline:
  2288. case no_split:
  2289. case no_spill:
  2290. case no_writespill:
  2291. case no_throughaggregate:
  2292. case no_limit:
  2293. case no_catchds:
  2294. case no_compound_fetch:
  2295. case no_topn:
  2296. case no_keyeddistribute:
  2297. case no_preload:
  2298. case no_catch:
  2299. case no_keyedlimit:
  2300. case no_keydiff:
  2301. case no_keypatch:
  2302. case no_activerow:
  2303. case no_assert_ds:
  2304. case no_spillgraphresult:
  2305. case no_sectioninput:
  2306. case no_forcegraph:
  2307. case no_related:
  2308. case no_outofline:
  2309. case no_fieldmap:
  2310. case no_owned_ds:
  2311. return false;
  2312. case no_iterate:
  2313. case no_rollup:
  2314. case no_loop:
  2315. case no_graphloop:
  2316. case no_newrow: //only used while transforming
  2317. case no_newaggregate:
  2318. case no_childdataset:
  2319. case no_denormalize:
  2320. case no_denormalizegroup:
  2321. case no_fetch:
  2322. case no_join:
  2323. case no_mergejoin:
  2324. case no_nwayjoin:
  2325. case no_nwaymerge:
  2326. case no_selfjoin:
  2327. case no_pipe:
  2328. case no_transformebcdic:
  2329. case no_transformascii:
  2330. case no_hqlproject:
  2331. case no_left:
  2332. case no_normalize:
  2333. case no_null:
  2334. case no_anon:
  2335. case no_pseudods:
  2336. case no_all:
  2337. case no_none:
  2338. case no_funcdef:
  2339. case no_right:
  2340. case no_selectfields:
  2341. case no_selectnth:
  2342. case no_self:
  2343. case no_top:
  2344. case no_table:
  2345. case no_temptable:
  2346. case no_inlinetable:
  2347. case no_xmlproject:
  2348. case no_workunit_dataset:
  2349. case no_newusertable:
  2350. case no_aggregate:
  2351. case no_usertable:
  2352. case no_keyindex:
  2353. case no_newkeyindex:
  2354. case no_if:
  2355. case no_map:
  2356. case no_case:
  2357. case no_chooseds:
  2358. case no_colon:
  2359. case no_globalscope:
  2360. case no_nothor:
  2361. case no_getresult:
  2362. case no_getgraphresult:
  2363. case no_getgraphloopresult:
  2364. case no_joincount:
  2365. case no_parse:
  2366. case no_xmlparse:
  2367. case no_newparse:
  2368. case no_newxmlparse:
  2369. case no_fail:
  2370. case no_skip:
  2371. case no_activetable:
  2372. case no_httpcall:
  2373. case no_soapcall:
  2374. case no_soapcall_ds:
  2375. case no_newsoapcall:
  2376. case no_newsoapcall_ds:
  2377. case no_alias:
  2378. case no_id2blob:
  2379. case no_embedbody:
  2380. case no_externalcall:
  2381. case no_projectrow:
  2382. case no_datasetfromrow:
  2383. case no_datasetfromdictionary:
  2384. case no_forcelocal: // for the moment this defines a table, otherwise the transforms get rather tricky.
  2385. case no_forcenolocal:
  2386. case no_allnodes:
  2387. case no_thisnode:
  2388. case no_createrow:
  2389. case no_typetransfer:
  2390. case no_translated:
  2391. case no_call:
  2392. case no_param:
  2393. case no_rows:
  2394. case no_combine:
  2395. case no_combinegroup:
  2396. case no_rollupgroup:
  2397. case no_cluster:
  2398. case no_internalselect:
  2399. case no_delayedselect:
  2400. case no_unboundselect:
  2401. case no_libraryselect:
  2402. case no_purevirtual:
  2403. case no_libraryinput:
  2404. case no_process:
  2405. case no_rowsetindex:
  2406. case no_rowsetrange:
  2407. case no_filtergroup:
  2408. case no_deserialize:
  2409. case no_serialize:
  2410. case no_commonspill:
  2411. case no_readspill:
  2412. case no_fromxml:
  2413. case no_normalizegroup:
  2414. case no_cogroup:
  2415. case no_dataset_alias:
  2416. case no_dataset_from_transform:
  2417. case no_mapto:
  2418. return true;
  2419. case no_select:
  2420. case no_field:
  2421. {
  2422. type_t tc = dataset->queryType()->getTypeCode();
  2423. assertex(tc == type_table || tc == type_groupedtable || tc == type_dictionary);
  2424. return true;
  2425. }
  2426. case no_comma:
  2427. return false;
  2428. case no_compound:
  2429. case no_executewhen:
  2430. return false;
  2431. default:
  2432. if (!dataset->isDataset())
  2433. return false;
  2434. PrintLogExprTree(dataset, "definesColumnList() missing operator: ");
  2435. assertex(false);
  2436. return true;
  2437. }
  2438. }
  2439. unsigned queryTransformIndex(IHqlExpression * expr)
  2440. {
  2441. node_operator op = expr->getOperator();
  2442. unsigned pos;
  2443. switch (op)
  2444. {
  2445. case no_createrow:
  2446. case no_typetransfer:
  2447. pos = 0;
  2448. break;
  2449. case no_transformebcdic:
  2450. case no_transformascii:
  2451. case no_hqlproject:
  2452. case no_projectrow:
  2453. case no_iterate:
  2454. case no_rollupgroup:
  2455. case no_xmlproject:
  2456. pos = 1;
  2457. break;
  2458. case no_newkeyindex:
  2459. case no_newaggregate:
  2460. case no_newusertable:
  2461. case no_aggregate:
  2462. case no_normalize:
  2463. case no_xmlparse:
  2464. case no_rollup:
  2465. case no_combine:
  2466. case no_combinegroup:
  2467. case no_process:
  2468. case no_nwayjoin:
  2469. pos = 2;
  2470. break;
  2471. case no_fetch:
  2472. case no_join:
  2473. case no_selfjoin:
  2474. case no_joincount:
  2475. case no_denormalize:
  2476. case no_denormalizegroup:
  2477. case no_parse:
  2478. case no_soapcall:
  2479. case no_newxmlparse:
  2480. pos = 3;
  2481. break;
  2482. case no_newparse:
  2483. case no_newsoapcall: // 4 because input(2) gets transformed.
  2484. case no_soapcall_ds:
  2485. pos = 4;
  2486. break;
  2487. case no_newsoapcall_ds:
  2488. pos = 5;
  2489. break;
  2490. default:
  2491. throwUnexpectedOp(op);
  2492. }
  2493. #ifdef _DEBUG
  2494. assertex(expr->queryChild(pos)->isTransform());
  2495. #endif
  2496. return pos;
  2497. }
  2498. IHqlExpression * queryNewColumnProvider(IHqlExpression * expr)
  2499. {
  2500. node_operator op = expr->getOperator();
  2501. switch (op)
  2502. {
  2503. case no_alias:
  2504. return expr->queryRecord();
  2505. case no_createrow:
  2506. case no_typetransfer:
  2507. return expr->queryChild(0);
  2508. case no_usertable:
  2509. case no_selectfields:
  2510. case no_transformebcdic:
  2511. case no_transformascii:
  2512. case no_hqlproject:
  2513. case no_dataset_from_transform:
  2514. case no_keyindex:
  2515. case no_projectrow:
  2516. case no_iterate:
  2517. case no_rollupgroup:
  2518. case no_xmlproject:
  2519. case no_deserialize:
  2520. case no_serialize:
  2521. return expr->queryChild(1);
  2522. case no_newkeyindex:
  2523. case no_aggregate:
  2524. case no_newaggregate:
  2525. case no_newusertable:
  2526. case no_normalize:
  2527. case no_xmlparse:
  2528. case no_rollup:
  2529. case no_combine:
  2530. case no_combinegroup:
  2531. case no_process:
  2532. case no_nwayjoin:
  2533. return expr->queryChild(2);
  2534. case no_fetch:
  2535. case no_join:
  2536. case no_selfjoin:
  2537. case no_joincount:
  2538. case no_denormalize:
  2539. case no_denormalizegroup:
  2540. case no_parse:
  2541. case no_soapcall:
  2542. case no_httpcall:
  2543. case no_newxmlparse:
  2544. return expr->queryChild(3);
  2545. case no_newparse:
  2546. case no_newsoapcall: // 4 because input(2) gets transformed.
  2547. case no_soapcall_ds:
  2548. return expr->queryChild(4);
  2549. case no_newsoapcall_ds:
  2550. return expr->queryChild(5);
  2551. default:
  2552. return NULL;
  2553. }
  2554. }
  2555. IHqlExpression * queryDatasetGroupBy(IHqlExpression * expr)
  2556. {
  2557. switch (expr->getOperator())
  2558. {
  2559. case no_newaggregate:
  2560. case no_newusertable:
  2561. case no_aggregate:
  2562. return queryRealChild(expr, 3);
  2563. case no_selectfields:
  2564. case no_usertable:
  2565. return queryRealChild(expr, 2);
  2566. }
  2567. return NULL;
  2568. }
  2569. bool datasetHasGroupBy(IHqlExpression * expr)
  2570. {
  2571. IHqlExpression * grouping = queryDatasetGroupBy(expr);
  2572. if (grouping)// && !grouping->isConstant())
  2573. return true;
  2574. return false;
  2575. }
  2576. bool isAggregateDataset(IHqlExpression * expr)
  2577. {
  2578. switch (expr->getOperator())
  2579. {
  2580. case no_aggregate:
  2581. case no_newaggregate:
  2582. return true;
  2583. case no_selectfields:
  2584. case no_usertable:
  2585. {
  2586. IHqlExpression * grouping = expr->queryChild(2);
  2587. if (grouping && !grouping->isAttribute())
  2588. return true;
  2589. return expr->queryChild(1)->isGroupAggregateFunction();
  2590. }
  2591. default:
  2592. return false;
  2593. }
  2594. }
  2595. bool isAggregatedDataset(IHqlExpression * expr)
  2596. {
  2597. loop
  2598. {
  2599. if (isAggregateDataset(expr))
  2600. return true;
  2601. switch (expr->getOperator())
  2602. {
  2603. case no_newusertable:
  2604. case no_selectfields:
  2605. case no_usertable:
  2606. expr = expr->queryChild(0);
  2607. break;
  2608. default:
  2609. return false;
  2610. }
  2611. }
  2612. }
  2613. IHqlExpression * ensureExprType(IHqlExpression * expr, ITypeInfo * type, node_operator castOp)
  2614. {
  2615. ITypeInfo * qualifiedType = expr->queryType();
  2616. if (qualifiedType == type)
  2617. return LINK(expr);
  2618. ITypeInfo * exprType = queryUnqualifiedType(qualifiedType);
  2619. if (exprType == queryUnqualifiedType(type))
  2620. return LINK(expr);
  2621. type_t tc = type->getTypeCode();
  2622. if (tc == type_any)
  2623. return LINK(expr);
  2624. if (tc == type_set)
  2625. {
  2626. ITypeInfo * childType = type->queryChildType();
  2627. if (!childType)
  2628. return LINK(expr);
  2629. if (exprType)
  2630. {
  2631. ITypeInfo * exprChildType = exprType->queryChildType();
  2632. if (exprChildType && isSameBasicType(childType, exprChildType))
  2633. return LINK(expr);
  2634. }
  2635. HqlExprArray values;
  2636. if (expr->getOperator() == no_list)
  2637. expr->unwindList(values, expr->getOperator());
  2638. else if (expr->getOperator() == no_null)
  2639. return createValue(no_list, LINK(type));
  2640. else if (exprType->getTypeCode() == type_array)
  2641. {
  2642. if (!childType || exprType->queryChildType() == childType)
  2643. return LINK(expr);
  2644. return createValue(castOp, LINK(type), LINK(expr));
  2645. }
  2646. else if (exprType->getTypeCode() == type_set)
  2647. {
  2648. if (!childType || isDatasetType(childType))
  2649. return LINK(expr);
  2650. if (expr->getOperator() == no_all)
  2651. return createValue(no_all, LINK(type));
  2652. if (expr->getOperator() == no_alias_scope)
  2653. {
  2654. HqlExprArray args;
  2655. unwindChildren(args, expr);
  2656. IHqlExpression * cast = ensureExprType(expr->queryChild(0), type, castOp);
  2657. args.replace(*cast,0);
  2658. return createValue(no_alias_scope, cast->getType(), args);
  2659. }
  2660. return createValue(castOp, LINK(type), LINK(expr));
  2661. }
  2662. else
  2663. {
  2664. // cvt single values to list
  2665. values.append(*LINK(expr));
  2666. }
  2667. Owned<ITypeInfo> promotedType;
  2668. ForEachItemIn(idx, values)
  2669. {
  2670. IHqlExpression * cast = ensureExprType(&values.item(idx), childType);
  2671. values.replace(*cast, idx);
  2672. ITypeInfo * castType = cast->queryType();
  2673. if (!promotedType)
  2674. promotedType.set(castType);
  2675. else if (!isSameBasicType(promotedType, castType))
  2676. {
  2677. if (promotedType->getSize() != UNKNOWN_LENGTH)
  2678. {
  2679. promotedType.setown(getStretchedType(UNKNOWN_LENGTH, childType));
  2680. }
  2681. }
  2682. }
  2683. if (promotedType && (childType->getSize() != UNKNOWN_LENGTH))
  2684. type = makeSetType(promotedType.getClear());
  2685. else
  2686. type->Link();
  2687. return createValue(no_list, type, values);
  2688. }
  2689. else if (tc == type_alien)
  2690. {
  2691. return ensureExprType(expr, type->queryPromotedType(), castOp);
  2692. }
  2693. else if (type->getSize() == UNKNOWN_LENGTH)
  2694. {
  2695. if (exprType)
  2696. {
  2697. //Optimize away casts to unknown length if the rest of the type matches.
  2698. if (exprType->getTypeCode() == tc)
  2699. {
  2700. //cast to STRING/DATA/VARSTRING/UNICODE/VARUNICODE means ensure that the expression has this base type.
  2701. if ((tc == type_data) || (tc == type_qstring))
  2702. {
  2703. return LINK(expr);
  2704. }
  2705. else if (tc == type_unicode || tc == type_varunicode || tc == type_utf8)
  2706. {
  2707. if (type->queryLocale() == exprType->queryLocale())
  2708. return LINK(expr);
  2709. }
  2710. else if (tc == type_string || tc == type_varstring)
  2711. {
  2712. if ((type->queryCharset() == exprType->queryCharset()) &&
  2713. (type->queryCollation() == exprType->queryCollation()))
  2714. return LINK(expr);
  2715. }
  2716. else if (tc == type_decimal)
  2717. {
  2718. if (type->isSigned() == exprType->isSigned())
  2719. return LINK(expr);
  2720. }
  2721. }
  2722. /*
  2723. The following might produce better code, but it generally makes things worse.....
  2724. if ((exprType->getSize() != UNKNOWN_LENGTH) && (isStringType(exprType) || isUnicodeType(exprType)))
  2725. {
  2726. Owned<ITypeInfo> stretchedType = getStretchedType(exprType->getStringLen(), type);
  2727. return ensureExprType(expr, stretchedType, castOp);
  2728. }
  2729. */
  2730. }
  2731. }
  2732. node_operator op = expr->getOperator();
  2733. if (op == no_null)
  2734. {
  2735. assertex(expr->queryRecord());
  2736. //The no_null can differ from the expected type by (i) link counting (ii) record annotations
  2737. assertex(recordTypesMatch(type, exprType));
  2738. return createNullExpr(type);
  2739. }
  2740. IValue * value = expr->queryValue();
  2741. if (value && type->assignableFrom(exprType)) // this last condition is unnecessary, but changes some persist crcs if removed
  2742. {
  2743. value = value->castTo(type);
  2744. if (value)
  2745. return createConstant(value);
  2746. }
  2747. switch (tc)
  2748. {
  2749. case type_row:
  2750. case type_transform:
  2751. {
  2752. switch (exprType->getTypeCode())
  2753. {
  2754. case type_row:
  2755. case type_transform:
  2756. if (recordTypesMatch(type, exprType))
  2757. return LINK(expr);
  2758. break;
  2759. }
  2760. }
  2761. case type_dictionary:
  2762. case type_table:
  2763. case type_groupedtable:
  2764. if (recordTypesMatch(type, exprType))
  2765. {
  2766. if (tc==type_dictionary && !expr->isDictionary())
  2767. return createDictionary(no_createdictionary, LINK(expr));
  2768. else
  2769. return LINK(expr);
  2770. }
  2771. assertex(!expr->isDictionary());
  2772. break;
  2773. case type_scope:
  2774. case type_function:
  2775. return LINK(expr);
  2776. }
  2777. //MORE: Casts of datasets should create a dataset - but there is no parameter to determine the type from...
  2778. switch (tc)
  2779. {
  2780. case type_table:
  2781. case type_groupedtable:
  2782. {
  2783. if (!expr->queryRecord())
  2784. return LINK(expr); // something seriously wrong - will get picked up elsewhere...
  2785. if(!queryOriginalRecord(type))
  2786. throwUnexpectedX("Cast to DATASET with no record TYPE specified"); // cf. HPCC-9847
  2787. OwnedHqlExpr transform = createRecordMappingTransform(no_newtransform, queryOriginalRecord(type), expr->queryNormalizedSelector());
  2788. if (transform)
  2789. return createDatasetF(no_newusertable, LINK(expr), LINK(queryOriginalRecord(type)), LINK(transform), NULL);
  2790. //Need to create a project of the dataset - error if can't
  2791. break;
  2792. }
  2793. case type_row:
  2794. {
  2795. OwnedHqlExpr input = isAlwaysActiveRow(expr) ? LINK(expr) : createRow(no_newrow, LINK(expr));
  2796. OwnedHqlExpr transform = createRecordMappingTransform(no_newtransform, queryOriginalRecord(type), input);
  2797. if (transform)
  2798. return createRow(no_createrow, LINK(transform));
  2799. //Need to create a project of the dataset - error if can't
  2800. break;
  2801. }
  2802. }
  2803. if (op == no_skip)
  2804. return createValue(no_skip, LINK(type), LINK(expr->queryChild(0)));
  2805. return createValue(castOp, LINK(type), LINK(expr));
  2806. }
  2807. extern HQL_API IHqlExpression * ensureExprType(IHqlExpression * expr, ITypeInfo * type)
  2808. {
  2809. return ensureExprType(expr, type, no_implicitcast);
  2810. }
  2811. extern HQL_API IHqlExpression * getCastExpr(IHqlExpression * expr, ITypeInfo * type)
  2812. {
  2813. return ensureExprType(expr, type, no_cast);
  2814. }
  2815. extern HQL_API IHqlExpression * normalizeListCasts(IHqlExpression * expr)
  2816. {
  2817. switch (expr->getOperator())
  2818. {
  2819. case no_cast:
  2820. case no_implicitcast:
  2821. {
  2822. IHqlExpression * arg = expr->queryChild(0);
  2823. OwnedHqlExpr normalized = normalizeListCasts(arg);
  2824. OwnedHqlExpr ret = ensureExprType(normalized, expr->queryType());
  2825. if (ret == expr->queryBody())
  2826. return LINK(expr);
  2827. return expr->cloneAllAnnotations(ret);
  2828. }
  2829. default:
  2830. return LINK(expr);
  2831. }
  2832. }
  2833. extern HQL_API IHqlExpression * simplifyFixedLengthList(IHqlExpression * expr)
  2834. {
  2835. if (expr->getOperator() != no_list)
  2836. return LINK(expr);
  2837. ITypeInfo * listType = expr->queryType();
  2838. ITypeInfo * elemType = listType->queryChildType();
  2839. if (!elemType || (elemType->getSize() != UNKNOWN_LENGTH))
  2840. return LINK(expr);
  2841. unsigned max = expr->numChildren();
  2842. if (max == 0)
  2843. return LINK(expr);
  2844. unsigned elemSize = UNKNOWN_LENGTH;
  2845. ForEachChild(i, expr)
  2846. {
  2847. unsigned thisSize = expr->queryChild(i)->queryType()->getStringLen();
  2848. if (thisSize == UNKNOWN_LENGTH)
  2849. return LINK(expr);
  2850. if (i == 0)
  2851. elemSize = thisSize;
  2852. else if (elemSize != thisSize)
  2853. return LINK(expr);
  2854. }
  2855. HqlExprArray args;
  2856. unwindChildren(args, expr);
  2857. return createValue(no_list, makeSetType(getStretchedType(elemSize, elemType)), args);
  2858. }
  2859. extern HQL_API IHqlExpression * expandBetween(IHqlExpression * expr)
  2860. {
  2861. IHqlExpression * test = expr->queryChild(0);
  2862. IHqlExpression * lower = expr->queryChild(1);
  2863. IHqlExpression * upper = expr->queryChild(2);
  2864. if (expr->getOperator() == no_between)
  2865. return createBoolExpr(no_and,
  2866. createBoolExpr(no_ge, LINK(test), LINK(lower)),
  2867. createBoolExpr(no_le, LINK(test), LINK(upper)));
  2868. else
  2869. return createBoolExpr(no_or,
  2870. createBoolExpr(no_lt, LINK(test), LINK(lower)),
  2871. createBoolExpr(no_gt, LINK(test), LINK(upper)));
  2872. }
  2873. //==============================================================================================================
  2874. #ifdef DEBUG_TRACK_INSTANCEID
  2875. static unsigned __int64 exprseqid;
  2876. #endif
  2877. CHqlExpression::CHqlExpression(node_operator _op)
  2878. {
  2879. #ifdef DEBUG_TRACK_INSTANCEID
  2880. //Not thread safe, but not much use if multi threading anyway.
  2881. seqid = ++exprseqid;
  2882. #endif
  2883. op = _op;
  2884. for (unsigned i=0; i < NUM_PARALLEL_TRANSFORMS; i++)
  2885. {
  2886. transformExtra[i] = NULL;
  2887. transformDepth[i] = 0;
  2888. }
  2889. hashcode = 0;
  2890. cachedCRC = 0;
  2891. attributes = NULL;
  2892. initFlagsBeforeOperands();
  2893. CHECK_EXPR_SEQID(0);
  2894. }
  2895. void CHqlExpression::appendOperands(IHqlExpression * arg0, ...)
  2896. {
  2897. if (!arg0)
  2898. return;
  2899. unsigned numArgs = 1;
  2900. va_list argscount;
  2901. va_start(argscount, arg0);
  2902. for (;;)
  2903. {
  2904. IHqlExpression *parm = va_arg(argscount, IHqlExpression *);
  2905. if (!parm)
  2906. break;
  2907. numArgs++;
  2908. }
  2909. va_end(argscount);
  2910. operands.ensure(numArgs);
  2911. doAppendOperand(*arg0);
  2912. va_list args;
  2913. va_start(args, arg0);
  2914. for (;;)
  2915. {
  2916. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  2917. if (!parm)
  2918. break;
  2919. #ifdef _DEBUG
  2920. assertex(QUERYINTERFACE(parm, IHqlExpression));
  2921. #endif
  2922. doAppendOperand(*parm);
  2923. }
  2924. va_end(args);
  2925. }
  2926. IIdAtom * CHqlExpression::queryId() const
  2927. {
  2928. assertex(!isAttribute());
  2929. return NULL;
  2930. }
  2931. void CHqlExpression::setOperands(HqlExprArray & _ownedOperands)
  2932. {
  2933. unsigned max = _ownedOperands.ordinality();
  2934. if (max)
  2935. {
  2936. operands.swapWith(_ownedOperands);
  2937. for (unsigned i=0; i < max; i++)
  2938. onAppendOperand(operands.item(i), i);
  2939. }
  2940. }
  2941. void CHqlExpression::initFlagsBeforeOperands()
  2942. {
  2943. //NB: The following code is not allowed to access queryType()!
  2944. infoFlags = 0;
  2945. infoFlags2 = 0;
  2946. if (::checkConstant(op)) infoFlags2 |= HEF2constant;
  2947. switch (op)
  2948. {
  2949. case NO_AGGREGATEGROUP:
  2950. infoFlags |= HEFfunctionOfGroupAggregate|HEFtransformDependent;
  2951. infoFlags2 &= ~(HEF2constant);
  2952. break;
  2953. case no_random:
  2954. infoFlags2 &= ~(HEF2constant);
  2955. infoFlags |= HEFvolatile;
  2956. break;
  2957. case no_wait:
  2958. infoFlags2 |= HEF2globalAction;
  2959. break;
  2960. case no_apply:
  2961. case no_buildindex:
  2962. case no_distribution:
  2963. case no_keydiff:
  2964. case no_keypatch:
  2965. case no_returnresult:
  2966. case no_setgraphresult:
  2967. case no_setgraphloopresult:
  2968. case no_impure:
  2969. case no_outputscalar:
  2970. case no_ensureresult:
  2971. case no_definesideeffect:
  2972. case no_callsideeffect:
  2973. infoFlags2 &= ~(HEF2constant);
  2974. infoFlags |= HEFaction;
  2975. break;
  2976. case no_fail:
  2977. case no_assert:
  2978. case no_assert_ds:
  2979. infoFlags2 &= ~(HEF2constant);
  2980. break;
  2981. case no_purevirtual:
  2982. infoFlags |= HEFcontextDependentException;
  2983. break;
  2984. case no_output:
  2985. case no_setresult:
  2986. case no_extractresult:
  2987. // don't mark as impure because temporary results don't get commoned up. Need another flag to mean has side-effects,
  2988. // but can be commoned up because repeating it will have the same effect.
  2989. infoFlags2 &= ~(HEF2constant);
  2990. break;
  2991. case no_skip:
  2992. infoFlags |= HEFcontainsSkip;
  2993. break;
  2994. case no_alias:
  2995. infoFlags |= HEFcontainsAlias|HEFcontainsAliasLocally;
  2996. break;
  2997. case no_dataset_alias:
  2998. if (!queryAttribute(_normalized_Atom))
  2999. infoFlags |= HEFcontainsDatasetAliasLocally;
  3000. break;
  3001. case no_activetable:
  3002. case no_activerow:
  3003. infoFlags2 &= ~(HEF2constant);
  3004. infoFlags |= HEFcontainsActiveDataset|HEFcontainsActiveNonSelector;
  3005. break;
  3006. case no_left:
  3007. case no_right:
  3008. case no_top:
  3009. infoFlags2 &= ~(HEF2constant);
  3010. infoFlags |= HEFcontainsActiveDataset;
  3011. break;
  3012. case no_nohoist:
  3013. infoFlags |= HEFcontextDependent;
  3014. infoFlags2 &= ~HEF2constant;
  3015. break;
  3016. case no_nofold:
  3017. case no_section: // not so sure about this...
  3018. case no_sectioninput:
  3019. case no_wuid:
  3020. case no_getenv:
  3021. infoFlags2 &= ~HEF2constant;
  3022. break;
  3023. case no_counter:
  3024. infoFlags |= (HEFcontainsCounter);
  3025. break;
  3026. case no_loopcounter:
  3027. infoFlags |= HEFgraphDependent;
  3028. break;
  3029. case no_matched:
  3030. case no_matchtext:
  3031. case no_matchunicode:
  3032. case no_matchlength:
  3033. case no_matchposition:
  3034. case no_matchattr:
  3035. case no_matchrow:
  3036. case no_matchutf8:
  3037. infoFlags2 &= ~(HEF2constant);
  3038. infoFlags |= HEFcontainsNlpText;
  3039. break;
  3040. case no_failcode:
  3041. case no_failmessage:
  3042. // case no_eventname:
  3043. // case no_eventextra:
  3044. //MORE: Really should improve on contextDependentException
  3045. //however we would need to make sure they were cleared by the correct transform
  3046. infoFlags2 &= ~(HEF2constant);
  3047. infoFlags |= HEFonFailDependent;
  3048. break;
  3049. case no_variable:
  3050. case no_quoted:
  3051. infoFlags2 &= ~(HEF2constant);
  3052. break;
  3053. case no_xmltext:
  3054. case no_xmlunicode:
  3055. case no_xmlproject:
  3056. infoFlags2 &= ~(HEF2constant);
  3057. infoFlags |= HEFcontainsXmlText;
  3058. break;
  3059. case no_assertkeyed:
  3060. case no_assertwild:
  3061. infoFlags |= HEFassertkeyed;
  3062. break;
  3063. case no_assertstepped:
  3064. infoFlags2 |= HEF2assertstepped;
  3065. break;
  3066. case no_filepos:
  3067. case no_file_logicalname:
  3068. infoFlags |= HEFcontainsActiveDataset|HEFcontainsActiveNonSelector;
  3069. break;
  3070. case no_getgraphresult:
  3071. case no_getgraphloopresult:
  3072. case no_libraryinput:
  3073. infoFlags |= HEFgraphDependent;
  3074. break;
  3075. case no_internalselect:
  3076. infoFlags |= HEFinternalSelect;
  3077. break;
  3078. case no_colon:
  3079. infoFlags2 |= HEF2workflow;
  3080. break;
  3081. case no_decimalstack:
  3082. infoFlags |= HEFaction;
  3083. break;
  3084. case no_getresult:
  3085. case no_workunit_dataset:
  3086. infoFlags |= HEFaccessRuntimeContext;
  3087. break;
  3088. }
  3089. }
  3090. void CHqlExpression::updateFlagsAfterOperands()
  3091. {
  3092. // DBGLOG("%p: Create(%s) type = %lx", (unsigned)(IHqlExpression *)this, getOpString(op), (unsigned)type);
  3093. switch (op)
  3094. {
  3095. case no_pure:
  3096. infoFlags &= ~(HEFvolatile|HEFaction|HEFthrowds|HEFthrowscalar|HEFcontainsSkip);
  3097. break;
  3098. case no_record:
  3099. {
  3100. unsigned num = numChildren();
  3101. unsigned idx;
  3102. for (idx = 0; idx < num; idx++)
  3103. {
  3104. IHqlExpression * cur = queryChild(idx);
  3105. if (cur->getOperator() == no_field)
  3106. {
  3107. //MORE: Should cope with
  3108. IHqlExpression * value = cur->queryChild(0);
  3109. if (value && value->isGroupAggregateFunction())
  3110. {
  3111. infoFlags |= HEFfunctionOfGroupAggregate;
  3112. break;
  3113. }
  3114. }
  3115. }
  3116. infoFlags &= ~(HEFcontextDependentException|HEFcontainsActiveDataset|HEFcontainsActiveNonSelector);
  3117. }
  3118. break;
  3119. case no_self:
  3120. {
  3121. ITypeInfo * thisType = queryType();
  3122. if (!thisType || !isPatternType(thisType))
  3123. {
  3124. infoFlags |= (HEFtransformDependent|HEFcontainsActiveDataset|HEFcontainsActiveNonSelector);
  3125. infoFlags2 |= HEF2containsSelf;
  3126. }
  3127. break;
  3128. }
  3129. case no_selfref: // not sure about what flags
  3130. {
  3131. ITypeInfo * thisType = queryType();
  3132. if (!thisType || !isPatternType(thisType))
  3133. infoFlags |= (HEFtransformDependent|HEFcontainsActiveDataset|HEFcontainsActiveNonSelector);
  3134. break;
  3135. }
  3136. case no_fail:
  3137. case no_assert:
  3138. case no_assert_ds:
  3139. switch (queryType()->getTypeCode())
  3140. {
  3141. case type_dictionary:
  3142. case type_table:
  3143. case type_groupedtable:
  3144. infoFlags |= HEFthrowds;
  3145. break;
  3146. default:
  3147. infoFlags |= HEFthrowscalar;
  3148. }
  3149. infoFlags |= HEFoldthrows;
  3150. break;
  3151. #if 0
  3152. //A good idea, but once temptables are marked as constant, I really should start constant folding them,
  3153. //otherwise the folder complains they weren't folded. Would be ok if values were fully expanded at normalize() time.
  3154. //In fact it would provide the basis for compile time record processing - which might have some interesting uses.
  3155. case no_temptable:
  3156. infoFlags |= (queryChild(0)->getInfoFlags() & (HEFconstant));
  3157. if (queryChild(2))
  3158. infoFlags &= (queryChild(2)->getInfoFlags() | ~(HEFconstant));
  3159. break;
  3160. #endif
  3161. case no_inlinetable:
  3162. infoFlags2 |= (queryChild(0)->getInfoFlags2() & (HEF2constant));
  3163. break;
  3164. case no_globalscope:
  3165. infoFlags2 |= HEF2mustHoist;
  3166. if (hasAttribute(optAtom))
  3167. break;
  3168. //fall through
  3169. case no_colon:
  3170. if (!isDataset() && !isDatarow())
  3171. {
  3172. infoFlags &= ~(HEFcontainsActiveDataset|HEFcontainsActiveNonSelector|HEFcontainsDataset);
  3173. }
  3174. break;
  3175. case NO_AGGREGATE:
  3176. infoFlags2 |= HEF2containsNewDataset;
  3177. if (queryChild(0) && (queryChild(0)->getOperator() == no_null))
  3178. infoFlags2 |= HEF2constant;
  3179. // don't percolate aliases beyond their subqueries at the moment.
  3180. infoFlags &= ~(HEFcontainsAliasLocally|HEFthrowscalar|HEFcontainsDatasetAliasLocally);
  3181. //a dataset fail, now becomes a scalar fail
  3182. if (infoFlags & HEFthrowds)
  3183. infoFlags = (infoFlags &~HEFthrowds)|HEFthrowscalar;
  3184. break;
  3185. case no_select:
  3186. if (!isNewSelector(this))
  3187. {
  3188. IHqlExpression * left = queryChild(0);
  3189. node_operator lOp = left->getOperator();
  3190. infoFlags = (infoFlags & HEFretainedByActiveSelect);
  3191. infoFlags |= HEFcontainsActiveDataset;
  3192. switch (lOp)
  3193. {
  3194. case no_self:
  3195. case no_left:
  3196. case no_right:
  3197. break;
  3198. default:
  3199. infoFlags |= HEFcontainsActiveNonSelector;
  3200. break;
  3201. }
  3202. }
  3203. else
  3204. {
  3205. infoFlags &= ~(HEFcontextDependentException|HEFcontainsActiveDataset|HEFcontainsAliasLocally|HEFcontainsDatasetAliasLocally|HEFthrowscalar); // don't percolate aliases beyond their subqueries at the moment.
  3206. infoFlags |= (queryChild(0)->getInfoFlags() & (HEFcontextDependentException|HEFcontainsActiveDataset));
  3207. if (infoFlags & HEFthrowds)
  3208. infoFlags = (infoFlags &~HEFthrowds)|HEFthrowscalar;
  3209. infoFlags2 |= HEF2containsNewDataset;
  3210. }
  3211. break;
  3212. case no_filepos:
  3213. case no_file_logicalname:
  3214. case no_joined:
  3215. infoFlags = (infoFlags & HEFretainedByActiveSelect);
  3216. infoFlags |= HEFcontainsActiveDataset|HEFcontainsActiveNonSelector;
  3217. break;
  3218. case no_offsetof:
  3219. case no_activerow:
  3220. case no_sizeof:
  3221. infoFlags = (infoFlags & HEFretainedByActiveSelect);
  3222. infoFlags |= HEFcontainsActiveDataset|HEFcontainsActiveNonSelector;
  3223. break;
  3224. case no_translated:
  3225. //could possibly make this dependent on adding an attribute to the expression.
  3226. infoFlags |= HEFtranslated;
  3227. break;
  3228. case no_transform:
  3229. case no_newtransform:
  3230. {
  3231. IHqlExpression * record = queryRecord();
  3232. if (record)
  3233. {
  3234. infoFlags |= (record->getInfoFlags() & HEFalwaysInherit);
  3235. infoFlags2 |= (record->getInfoFlags2() & HEF2alwaysInherit);
  3236. }
  3237. }
  3238. break;
  3239. case no_null:
  3240. infoFlags2 |= HEF2constant;
  3241. break;
  3242. case no_attr:
  3243. infoFlags = (infoFlags & (HEFhousekeeping|HEFalwaysInherit));
  3244. infoFlags2 |= HEF2constant;
  3245. break;
  3246. case no_newxmlparse:
  3247. case no_xmlparse:
  3248. //clear flag unless set in the dataset.
  3249. if (!(queryChild(0)->getInfoFlags() & HEFcontainsXmlText))
  3250. infoFlags &= ~HEFcontainsXmlText;
  3251. break;
  3252. case no_newparse:
  3253. case no_parse:
  3254. if (!(queryChild(0)->getInfoFlags() & HEFcontainsNlpText))
  3255. infoFlags &= ~HEFcontainsNlpText;
  3256. break;
  3257. case no_assign:
  3258. infoFlags = (infoFlags & ~HEFassigninheritFlags) | (queryChild(1)->getInfoFlags() & HEFassigninheritFlags);
  3259. infoFlags2 = (infoFlags2 & ~HEF2assigninheritFlags) | (queryChild(1)->getInfoFlags2() & HEF2assigninheritFlags);
  3260. infoFlags &= ~HEFcontainsDataset;
  3261. assertex(queryChild(0)->isDictionary() == queryChild(1)->isDictionary());
  3262. break;
  3263. case no_internalselect:
  3264. assertex(!queryChild(3)->isAttribute());
  3265. break;
  3266. case no_delayedselect:
  3267. case no_libraryselect:
  3268. case no_unboundselect:
  3269. assertex(!queryChild(3)->isAttribute());
  3270. //kill any flag derived from selecting pure virtual members
  3271. infoFlags &= ~HEFcontextDependentException;
  3272. break;
  3273. case no_attr_link:
  3274. case no_attr_expr:
  3275. if (queryName() == onFailAtom)
  3276. {
  3277. infoFlags &= ~(HEFonFailDependent|HEFcontainsSkip); // ONFAIL(SKIP) - skip shouldn't extend any further
  3278. }
  3279. infoFlags &= ~(HEFthrowscalar|HEFthrowds|HEFoldthrows);
  3280. break;
  3281. case no_clustersize:
  3282. //wrong, but improves the generated code
  3283. infoFlags |= HEFvolatile;
  3284. break;
  3285. case no_type:
  3286. {
  3287. HqlExprArray kids;
  3288. IHqlScope * scope = queryScope();
  3289. if (scope)
  3290. {
  3291. IHqlExpression * scopeExpr = queryExpression(scope);
  3292. if (scopeExpr)
  3293. {
  3294. infoFlags |= (scopeExpr->getInfoFlags() & HEFalwaysInherit);
  3295. infoFlags2 |= (scopeExpr->getInfoFlags2() & HEF2alwaysInherit);
  3296. }
  3297. }
  3298. break;
  3299. }
  3300. case no_thisnode:
  3301. infoFlags |= HEFcontainsThisNode;
  3302. break;
  3303. case no_getgraphresult:
  3304. if (hasAttribute(_streaming_Atom))
  3305. infoFlags2 |= HEF2mustHoist;
  3306. break;
  3307. case no_getgraphloopresult:
  3308. infoFlags2 |= HEF2mustHoist;
  3309. break;
  3310. case no_alias:
  3311. if (queryAttribute(globalAtom))
  3312. infoFlags2 &= ~HEF2containsNonGlobalAlias;
  3313. else
  3314. infoFlags2 |= HEF2containsNonGlobalAlias;
  3315. break;
  3316. case no_param:
  3317. infoFlags |= HEFgraphDependent; // Need something better
  3318. infoFlags2 &= ~HEF2workflow;
  3319. break;
  3320. case no_failure:
  3321. infoFlags &= ~HEFonFailDependent;
  3322. break;
  3323. case no_externalcall:
  3324. if (constant())
  3325. {
  3326. IHqlExpression * body = queryExternalDefinition()->queryChild(0);
  3327. assertex(body);
  3328. if (!body->hasAttribute(pureAtom))
  3329. infoFlags2 &= ~HEF2constant;
  3330. }
  3331. break;
  3332. case no_call:
  3333. {
  3334. IHqlExpression * funcdef = queryBody()->queryFunctionDefinition();
  3335. IHqlExpression * body = funcdef->queryChild(0);
  3336. if ((funcdef->getOperator() == no_funcdef) && (body->getOperator() == no_outofline))
  3337. {
  3338. infoFlags2 |= HEF2containsCall;
  3339. IHqlExpression * bodycode = body->queryChild(0);
  3340. if (bodycode->getOperator() == no_embedbody)
  3341. {
  3342. if (bodycode->queryAttribute(actionAtom))
  3343. infoFlags |= HEFvolatile;
  3344. }
  3345. }
  3346. else
  3347. infoFlags2 |= (HEF2containsCall|HEF2containsDelayedCall);
  3348. break;
  3349. }
  3350. case no_workunit_dataset:
  3351. case no_getresult:
  3352. {
  3353. if (false && matchesConstantValue(queryAttributeChild(this, sequenceAtom, 0), ResultSequenceOnce))
  3354. infoFlags |= HEFvolatile;
  3355. break;
  3356. }
  3357. case no_embedbody:
  3358. {
  3359. if (queryAttribute(actionAtom))
  3360. infoFlags |= HEFvolatile;
  3361. break;
  3362. }
  3363. }
  3364. #ifdef VERIFY_EXPR_INTEGRITY
  3365. switch (op)
  3366. {
  3367. case no_select:
  3368. #ifdef CHECK_RECORD_CONSISTENCY
  3369. {
  3370. //Paranoid check to ensure that illegal no_selects aren't created (e.g., when dataset has link counted child, but field of select isn't)
  3371. IHqlExpression * field = queryChild(1);
  3372. IHqlExpression * lhsRecord = queryChild(0)->queryRecord();
  3373. if (lhsRecord && lhsRecord->numChildren() && field->getOperator() == no_field)
  3374. {
  3375. OwnedHqlExpr resolved = lhsRecord->querySimpleScope()->lookupSymbol(field->queryId());
  3376. if (resolved && resolved != field)
  3377. EclIR::dump_ir(resolved.get(), field);
  3378. assertex(!resolved || resolved == field);
  3379. }
  3380. }
  3381. #endif
  3382. break;
  3383. case no_translated:
  3384. assertex(queryUnqualifiedType(queryType()) == queryUnqualifiedType(queryChild(0)->queryType()));
  3385. break;
  3386. case no_transform:
  3387. case no_newtransform:
  3388. {
  3389. // assertex(op != no_newtransform || !queryChildOperator(no_assignall, this));
  3390. assertex(queryType() && queryType()->getTypeCode() == type_transform);
  3391. }
  3392. break;
  3393. case no_assign:
  3394. #ifdef CHECK_RECORD_CONSISTENCY
  3395. assertex(queryChild(0)->getOperator() != no_assign);
  3396. assertex(queryChild(1)->getOperator() != no_assign);
  3397. {
  3398. IHqlExpression * lhsRecord = queryChild(0)->queryRecord();
  3399. IHqlExpression * rhsRecord = queryChild(1)->queryRecord();
  3400. if (lhsRecord && rhsRecord)
  3401. {
  3402. //This condition can be broken inside a transform that changes the types of fields.
  3403. //It could possibly be avoided by more selective calls to transform.
  3404. assertex(recordTypesMatch(lhsRecord, rhsRecord));
  3405. }
  3406. }
  3407. #endif
  3408. #ifdef PARANOID
  3409. assertex(queryChild(1)->getOperator() != no_field);
  3410. #endif
  3411. break;
  3412. #ifdef PARANOID
  3413. case no_field:
  3414. assertex(!queryChild(0) || queryChild(0)->getOperator() != no_field);
  3415. break;
  3416. #endif
  3417. case no_self:
  3418. assertex(queryType());
  3419. break;
  3420. case no_getresult:
  3421. {
  3422. assertex(!isAction());
  3423. break;
  3424. }
  3425. case no_and:
  3426. case no_or:
  3427. assertex(queryChild(1));
  3428. break;
  3429. case no_getgraphresult:
  3430. assertex(!isAction());
  3431. break;
  3432. case no_getgraphloopresult:
  3433. assertex(!isAction());
  3434. break;
  3435. case no_in:
  3436. case no_notin:
  3437. case no_eq:
  3438. case no_ne:
  3439. case no_ge:
  3440. case no_gt:
  3441. case no_le:
  3442. case no_lt:
  3443. assertex(queryType()->getTypeCode() == type_boolean);
  3444. break;
  3445. case no_funcdef:
  3446. {
  3447. assertex(queryType()->getTypeCode() == type_function && queryChild(1) && queryChild(1)->getOperator() == no_sortlist);
  3448. assertex(queryType()->queryChildType() == queryChild(0)->queryType());
  3449. break;
  3450. }
  3451. case no_setresult:
  3452. case no_extractresult:
  3453. {
  3454. IHqlExpression * child = queryChild(0);
  3455. //Don't do setresult, outputs completely in thor because thor can't do the necessary setresults. Yet.
  3456. assertex(!(child->getOperator() == no_thor && child->queryType()->getTypeCode() != type_void));
  3457. break;
  3458. }
  3459. case no_implicitcast:
  3460. assertex(queryType()->getTypeCode() != type_function);
  3461. assertex(queryChild(0)->queryType()->getTypeCode() != type_function);
  3462. break;
  3463. case no_newsoapcall:
  3464. case no_soapcall:
  3465. {
  3466. IHqlExpression * onFail = queryAttribute(onFailAtom);
  3467. if (onFail)
  3468. {
  3469. IHqlExpression * transform = onFail->queryChild(0);
  3470. if (transform->getOperator() != no_skip)
  3471. assertex(recordTypesMatch(transform, this));
  3472. }
  3473. break;
  3474. }
  3475. case no_indict:
  3476. assertex(queryChild(1)->isDictionary());
  3477. break;
  3478. case no_countdict:
  3479. assertex(queryChild(0)->isDictionary());
  3480. break;
  3481. }
  3482. #ifdef _DEBUG
  3483. if (op == no_select)
  3484. {
  3485. IHqlExpression * ds = queryChild(0);
  3486. if ((ds->getOperator() == no_select) && !ds->isDataset())
  3487. {
  3488. assertex(!hasAttribute(newAtom));
  3489. if (hasAttribute(newAtom) && isNewSelector(ds))
  3490. {
  3491. IHqlExpression * root = queryDatasetCursor(ds);
  3492. if (root->isDataset())
  3493. throwUnexpected();
  3494. }
  3495. }
  3496. }
  3497. #endif
  3498. #if 0
  3499. //Useful code for detecting when types get messed up for comparisons
  3500. if (op == no_eq || op == no_ne)
  3501. {
  3502. IHqlExpression * left = queryChild(0);
  3503. IHqlExpression * right = queryChild(1);
  3504. ITypeInfo * leftType = left->queryType()->queryPromotedType();
  3505. ITypeInfo * rightType = right->queryType()->queryPromotedType();
  3506. if (!areTypesComparable(leftType,rightType))
  3507. left = right;
  3508. }
  3509. #endif
  3510. #endif // _DEBUG
  3511. ITypeInfo * thisType = queryType();
  3512. if (thisType)
  3513. {
  3514. type_t tc = thisType->getTypeCode();
  3515. switch (tc)
  3516. {
  3517. case type_alien:
  3518. case type_scope:
  3519. {
  3520. IHqlExpression * typeExpr = queryExpression(thisType);
  3521. if (typeExpr)
  3522. {
  3523. infoFlags |= (typeExpr->getInfoFlags() & HEFalwaysInherit);
  3524. infoFlags2 |= (typeExpr->getInfoFlags2() & HEF2alwaysInherit);
  3525. }
  3526. break;
  3527. }
  3528. case type_dictionary:
  3529. case type_groupedtable:
  3530. case type_table:
  3531. {
  3532. //Not strictly true for nested counters..
  3533. infoFlags &= ~HEFcontainsCounter;
  3534. }
  3535. //fall through
  3536. case type_row:
  3537. case type_transform:
  3538. {
  3539. IHqlExpression * record = queryRecord();
  3540. if (record)
  3541. {
  3542. infoFlags |= (record->getInfoFlags() & HEFalwaysInherit);
  3543. infoFlags2 |= (record->getInfoFlags2() & HEF2alwaysInherit);
  3544. }
  3545. switch (op)
  3546. {
  3547. case no_fail: case no_assert: case no_assert_ds: case no_externalcall: case no_libraryscopeinstance:
  3548. case no_call:
  3549. break;
  3550. case no_transform: case no_newtransform:
  3551. infoFlags &= ~HEFoldthrows;
  3552. break;
  3553. default:
  3554. infoFlags &= ~HEFthrowscalar;
  3555. infoFlags &= ~HEFoldthrows;
  3556. if (tc == type_row)
  3557. infoFlags &= ~HEFthrowds;
  3558. break;
  3559. }
  3560. break;
  3561. }
  3562. case type_void:
  3563. if (op != no_assign)
  3564. infoFlags &= ~HEFthrowds;
  3565. break;
  3566. }
  3567. }
  3568. #ifdef CHECK_SELSEQ_CONSISTENCY
  3569. unsigned uidCount = 0;
  3570. ForEachChild(i, this)
  3571. {
  3572. IHqlExpression * cur = queryChild(i);
  3573. if (cur->isAttribute() && cur->queryName() == _uid_Atom)
  3574. uidCount++;
  3575. }
  3576. switch (uidCount)
  3577. {
  3578. case 0:
  3579. assertex(!definesColumnList(this));
  3580. break;
  3581. case 1:
  3582. if (queryRecord())
  3583. assertex(definesColumnList(this));
  3584. break;
  3585. default:
  3586. throwUnexpected();
  3587. }
  3588. /*
  3589. switch (getChildDatasetType(this))
  3590. {
  3591. case childdataset_left:
  3592. case childdataset_leftright:
  3593. case childdataset_same_left_right:
  3594. case childdataset_top_left_right:
  3595. case childdataset_datasetleft:
  3596. case childdataset_nway_left_right:
  3597. assertex(op == no_keydiff || querySelSeq(this));
  3598. break;
  3599. }
  3600. */
  3601. #endif
  3602. }
  3603. void CHqlExpression::onAppendOperand(IHqlExpression & child, unsigned whichOperand)
  3604. {
  3605. //MORE: All methods that use flags updated here need to be overridden in CHqlNamedExpr()
  3606. bool updateFlags = true;
  3607. unsigned childFlags = child.getInfoFlags();
  3608. unsigned childFlags2 = child.getInfoFlags2();
  3609. node_operator childOp = child.getOperator();
  3610. switch (op)
  3611. {
  3612. case no_keyindex:
  3613. case no_newkeyindex:
  3614. case no_joined:
  3615. if (whichOperand == 0)
  3616. updateFlags = false;
  3617. break;
  3618. case no_activerow:
  3619. updateFlags = false;
  3620. break;
  3621. case no_sizeof:
  3622. case no_offsetof:
  3623. case no_param: // don't inherit attributes of default values in the function body.
  3624. case no_nameof:
  3625. updateFlags = false;
  3626. break;
  3627. case no_limit:
  3628. case no_keyedlimit:
  3629. if (whichOperand > 1)
  3630. childFlags &= ~(HEFthrowscalar|HEFthrowds);
  3631. break;
  3632. #ifdef _DEBUG
  3633. case no_transform:
  3634. {
  3635. switch (childOp)
  3636. {
  3637. case no_assign:
  3638. case no_assignall:
  3639. case no_attr:
  3640. case no_attr_link:
  3641. case no_attr_expr:
  3642. case no_alias_scope:
  3643. case no_skip:
  3644. case no_assert:
  3645. break;
  3646. default:
  3647. UNIMPLEMENTED;
  3648. }
  3649. break;
  3650. }
  3651. case no_record:
  3652. {
  3653. switch (childOp)
  3654. {
  3655. case no_field:
  3656. case no_ifblock:
  3657. case no_record:
  3658. case no_attr:
  3659. case no_attr_expr:
  3660. case no_attr_link:
  3661. break;
  3662. default:
  3663. UNIMPLEMENTED;
  3664. }
  3665. break;
  3666. }
  3667. #endif
  3668. }
  3669. switch (childOp)
  3670. {
  3671. case no_transform:
  3672. case no_newtransform:
  3673. childFlags &= ~(HEFtransformDependent|HEFcontainsSkip|HEFthrowscalar|HEFthrowds);
  3674. break;
  3675. }
  3676. if (updateFlags)
  3677. {
  3678. //These are cleared if not set in the child.
  3679. infoFlags &= (childFlags | ~(HEFintersectionFlags));
  3680. //These are set if set in the child
  3681. infoFlags |= (childFlags & HEFunionFlags);
  3682. infoFlags2 &= (childFlags2 | ~(HEF2intersectionFlags));
  3683. infoFlags2 |= (childFlags2 & HEF2unionFlags);
  3684. }
  3685. else
  3686. {
  3687. infoFlags |= (childFlags & HEFalwaysInherit);
  3688. infoFlags2 |= (childFlags2 & HEF2alwaysInherit);
  3689. }
  3690. #ifdef _DEBUG
  3691. //This should never occur on legal code, but can occur on illegal, so only check in debug mode.
  3692. if (childOp == no_field)
  3693. assertex(op == no_record || op == no_select || op == no_comma || op == no_attr || op == no_attr_expr || op == no_indirect);
  3694. #endif
  3695. }
  3696. CHqlExpression::~CHqlExpression()
  3697. {
  3698. // DBGLOG("%lx: Destroy", (unsigned)(IHqlExpression *)this);
  3699. delete attributes;
  3700. }
  3701. IHqlScope * CHqlExpression::queryScope()
  3702. {
  3703. //better, especially in cascaded error situations..
  3704. if (op == no_compound)
  3705. return queryChild(1)->queryScope();
  3706. return NULL;
  3707. }
  3708. IHqlSimpleScope * CHqlExpression::querySimpleScope()
  3709. {
  3710. if (op == no_compound)
  3711. return queryChild(1)->querySimpleScope();
  3712. return NULL;
  3713. }
  3714. #define HASHFIELD(p) hashcode = hashc((unsigned char *) &p, sizeof(p), hashcode)
  3715. void CHqlExpression::setInitialHash(unsigned typeHash)
  3716. {
  3717. hashcode = op+typeHash;
  3718. unsigned kids = operands.ordinality();
  3719. hashcode = hashc((const unsigned char *)operands.getArray(), kids * sizeof(IHqlExpression *), hashcode);
  3720. }
  3721. void CHqlExpression::sethash()
  3722. {
  3723. // In 64-bit, just use bottom 32-bits of the ptr for the hash
  3724. setInitialHash((unsigned) (memsize_t) queryType());
  3725. }
  3726. unsigned CHqlExpression::getCachedEclCRC()
  3727. {
  3728. if (cachedCRC)
  3729. return cachedCRC;
  3730. unsigned crc = op;
  3731. switch (op)
  3732. {
  3733. case no_record:
  3734. case no_type:
  3735. break;
  3736. case no_self:
  3737. //ignore new record argument
  3738. cachedCRC = crc;
  3739. return crc;
  3740. case no_selfref:
  3741. crc = no_self;
  3742. break;
  3743. case no_assertconstant:
  3744. case no_assertconcrete:
  3745. return queryChild(0)->getCachedEclCRC();
  3746. case no_sortlist:
  3747. //backward compatibility
  3748. break;
  3749. case no_attr_expr:
  3750. {
  3751. const IAtom * name = queryBody()->queryName();
  3752. //Horrible backward compatibility "fix" for record crcs - they need to remain the same otherwise files
  3753. //will be incompatible.
  3754. if (name == maxLengthAtom || name == xpathAtom || name == cardinalityAtom || name == caseAtom || name == maxCountAtom || name == choosenAtom || name == maxSizeAtom || name == namedAtom || name == rangeAtom || name == xmlDefaultAtom || name == virtualAtom)
  3755. crc = no_attr;
  3756. //fallthrough
  3757. }
  3758. default:
  3759. {
  3760. ITypeInfo * thisType = queryType();
  3761. if (thisType && this != queryExpression(thisType))
  3762. {
  3763. ITypeInfo * hashType = thisType;
  3764. switch (hashType->getTypeCode())
  3765. {
  3766. case type_transform:
  3767. hashType = hashType->queryChildType();
  3768. break;
  3769. case type_row:
  3770. //Backward compatibility
  3771. if (op == no_field)
  3772. hashType = hashType->queryChildType();
  3773. break;
  3774. }
  3775. unsigned typeCRC = hashType->getCrc();
  3776. crc = hashc((const byte *)&typeCRC, sizeof(typeCRC), crc);
  3777. }
  3778. break;
  3779. }
  3780. }
  3781. unsigned numChildrenToHash = numChildren();
  3782. switch (op)
  3783. {
  3784. case no_constant:
  3785. crc = queryValue()->getHash(crc);
  3786. break;
  3787. case no_field:
  3788. {
  3789. IAtom * name = queryName();
  3790. if (name)
  3791. {
  3792. const char * nameText = name->str();
  3793. if ((nameText[0] != '_') || (nameText[1] != '_'))
  3794. crc = hashnc((const byte *)nameText, strlen(nameText), crc);
  3795. }
  3796. IHqlExpression * record = queryRecord();
  3797. if (record)
  3798. crc ^= record->getCachedEclCRC();
  3799. break;
  3800. }
  3801. case no_call:
  3802. crc ^= queryBody()->queryFunctionDefinition()->getCachedEclCRC();
  3803. break;
  3804. case no_externalcall:
  3805. case no_attr:
  3806. case no_attr_expr:
  3807. case no_attr_link:
  3808. {
  3809. const IAtom * name = queryBody()->queryName();
  3810. if (name == _uid_Atom)
  3811. return 0;
  3812. const char * nameText = name->str();
  3813. crc = hashnc((const byte *)nameText, strlen(nameText), crc);
  3814. break;
  3815. }
  3816. case no_libraryscopeinstance:
  3817. {
  3818. IHqlExpression * scopeFunc = queryDefinition();
  3819. IHqlExpression * moduleExpr = scopeFunc->queryChild(0);
  3820. crc ^= moduleExpr->getCachedEclCRC();
  3821. break;
  3822. }
  3823. case no_libraryscope:
  3824. case no_virtualscope:
  3825. {
  3826. //include information about symbols in the library scope crc, so that if the interface changes it forces a rebuild.
  3827. HqlExprArray symbols;
  3828. queryScope()->getSymbols(symbols);
  3829. symbols.sort(compareSymbolsByName);
  3830. ForEachItemIn(i, symbols)
  3831. {
  3832. IHqlExpression & cur = symbols.item(i);
  3833. if (cur.isExported())
  3834. {
  3835. unsigned crc2 = symbols.item(i).getCachedEclCRC();
  3836. crc = hashc((const byte *)&crc2, sizeof(crc2), crc);
  3837. }
  3838. }
  3839. break;
  3840. }
  3841. }
  3842. for (unsigned idx=0; idx < numChildrenToHash; idx++)
  3843. {
  3844. unsigned childCRC = queryChild(idx)->getCachedEclCRC();
  3845. if (childCRC)
  3846. crc = hashc((const byte *)&childCRC, sizeof(childCRC), crc);
  3847. }
  3848. cachedCRC = crc;
  3849. return crc;
  3850. }
  3851. bool CHqlExpression::equals(const IHqlExpression & other) const
  3852. {
  3853. if (!isAlive()) return false;
  3854. #ifndef CONSISTENCY_CHECK
  3855. if (this == &other)
  3856. return true;
  3857. #endif
  3858. if (other.isAnnotation())
  3859. return false;
  3860. if (op != other.getOperator())
  3861. return false;
  3862. switch (op)
  3863. {
  3864. case no_record:
  3865. case no_type:
  3866. case no_scope:
  3867. case no_service:
  3868. case no_virtualscope:
  3869. case no_concretescope:
  3870. case no_libraryscope:
  3871. case no_libraryscopeinstance:
  3872. break;
  3873. default:
  3874. if (queryType() != other.queryType())
  3875. return false;
  3876. break;
  3877. }
  3878. unsigned kids = other.numChildren();
  3879. if (kids != numChildren())
  3880. return false;
  3881. for (unsigned kid = 0; kid < kids; kid++)
  3882. {
  3883. if (queryChild(kid) != other.queryChild(kid))
  3884. return false;
  3885. }
  3886. return true;
  3887. }
  3888. IHqlExpression *CHqlExpression::closeExpr()
  3889. {
  3890. assertex(!isExprClosed()); // closeExpr() shouldn't be called twice
  3891. updateFlagsAfterOperands();
  3892. sethash();
  3893. return commonUpExpression();
  3894. }
  3895. IHqlScope * closeScope(IHqlScope * scope)
  3896. {
  3897. IHqlExpression * expr = queryExpression(scope);
  3898. return expr->closeExpr()->queryScope();
  3899. }
  3900. bool getAttribute(IHqlExpression * expr, IAtom * propname, StringBuffer &ret)
  3901. {
  3902. IHqlExpression* match = expr->queryAttribute(propname);
  3903. if (match)
  3904. {
  3905. IHqlExpression * value = match->queryChild(0);
  3906. if (value)
  3907. value->queryValue()->getStringValue(ret);
  3908. return true;
  3909. }
  3910. return false;
  3911. }
  3912. IHqlExpression *CHqlExpression::queryAttribute(IAtom * propname) const
  3913. {
  3914. unsigned kids = numChildren();
  3915. for (unsigned i = 0; i < kids; i++)
  3916. {
  3917. IHqlExpression *kid = queryChild(i);
  3918. if (kid->isAttribute() && kid->queryName()==propname)
  3919. return kid;
  3920. }
  3921. return NULL;
  3922. }
  3923. unsigned CHqlExpression::getSymbolFlags() const
  3924. {
  3925. throwUnexpected();
  3926. return 0;
  3927. }
  3928. IHqlExpression *CHqlExpression::queryChild(unsigned idx) const
  3929. {
  3930. if (operands.isItem(idx))
  3931. return &operands.item(idx);
  3932. else
  3933. return NULL;
  3934. }
  3935. unsigned CHqlExpression::numChildren() const
  3936. {
  3937. return operands.length();
  3938. }
  3939. IHqlExpression *CHqlExpression::addOperand(IHqlExpression * child)
  3940. {
  3941. //Forward scopes are never commoned up, and are shared as a side-effect of keeping references to their owner
  3942. assertex (!IsShared() || (op == no_forwardscope));
  3943. assertex (!isExprClosed());
  3944. doAppendOperand(*child);
  3945. return this;
  3946. }
  3947. inline bool matchesTypeCode(ITypeInfo * type, type_t search)
  3948. {
  3949. loop
  3950. {
  3951. if (!type)
  3952. return false;
  3953. type_t tc = type->getTypeCode();
  3954. if (tc == search)
  3955. return true;
  3956. if (tc != type_function)
  3957. return false;
  3958. type = type->queryChildType();
  3959. }
  3960. }
  3961. bool CHqlExpression::isBoolean()
  3962. {
  3963. return matchesTypeCode(queryType(), type_boolean);
  3964. }
  3965. bool CHqlExpression::isConstant()
  3966. {
  3967. return constant();
  3968. }
  3969. bool CHqlExpression::isDataset()
  3970. {
  3971. ITypeInfo * cur = queryType();
  3972. loop
  3973. {
  3974. if (!cur)
  3975. return false;
  3976. switch(cur->getTypeCode())
  3977. {
  3978. case type_groupedtable:
  3979. case type_table:
  3980. return true;
  3981. case type_function:
  3982. cur = cur->queryChildType();
  3983. break;
  3984. default:
  3985. return false;
  3986. }
  3987. }
  3988. }
  3989. bool CHqlExpression::isDictionary()
  3990. {
  3991. return matchesTypeCode(queryType(), type_dictionary);
  3992. }
  3993. bool CHqlExpression::isDatarow()
  3994. {
  3995. return matchesTypeCode(queryType(), type_row);
  3996. }
  3997. bool CHqlExpression:: isFunction()
  3998. {
  3999. ITypeInfo * thisType = queryType();
  4000. return thisType && thisType->getTypeCode() == type_function;
  4001. }
  4002. bool CHqlExpression::isMacro()
  4003. {
  4004. switch (op)
  4005. {
  4006. case no_macro:
  4007. return true;
  4008. case no_funcdef:
  4009. return queryChild(0)->isMacro();
  4010. }
  4011. return false;
  4012. }
  4013. bool CHqlExpression::isRecord()
  4014. {
  4015. return matchesTypeCode(queryType(), type_record);
  4016. }
  4017. bool CHqlExpression::isAction()
  4018. {
  4019. return matchesTypeCode(queryType(), type_void);
  4020. }
  4021. bool CHqlExpression::isTransform()
  4022. {
  4023. return matchesTypeCode(queryType(), type_transform);
  4024. }
  4025. bool CHqlExpression::isScope()
  4026. {
  4027. return matchesTypeCode(queryType(), type_scope);
  4028. }
  4029. bool CHqlExpression::isField()
  4030. {
  4031. return op == no_field;
  4032. }
  4033. bool CHqlExpression::isType()
  4034. {
  4035. switch(op)
  4036. {
  4037. case no_type:
  4038. return true;
  4039. case no_funcdef:
  4040. return queryChild(0)->isType();
  4041. default:
  4042. return false;
  4043. }
  4044. }
  4045. bool CHqlExpression::isList()
  4046. {
  4047. return matchesTypeCode(queryType(), type_set);
  4048. }
  4049. bool CHqlExpression::isAggregate()
  4050. {
  4051. //This is only used for HOLe processing - I'm not sure how much sense it really makes.
  4052. switch(op)
  4053. {
  4054. case NO_AGGREGATE:
  4055. case NO_AGGREGATEGROUP:
  4056. case no_distribution:
  4057. case no_selectnth:
  4058. case no_evaluate:
  4059. return true;
  4060. case no_select:
  4061. return (queryChild(0)->getOperator() == no_selectnth);
  4062. default:
  4063. return false;
  4064. }
  4065. }
  4066. StringBuffer &CHqlExpression::toString(StringBuffer &ret)
  4067. {
  4068. #ifdef TRACE_THIS
  4069. ret.appendf("[%lx]", this);
  4070. #endif
  4071. ret.appendf("%s", getOpString(op));
  4072. return ret;
  4073. }
  4074. void CHqlExpression::unwindList(HqlExprArray &dst, node_operator u_op)
  4075. {
  4076. if (op==u_op)
  4077. {
  4078. ForEachChild(idx, this)
  4079. queryChild(idx)->unwindList(dst, u_op);
  4080. }
  4081. else
  4082. {
  4083. Link();
  4084. dst.append((IHqlExpression &)*this);
  4085. }
  4086. }
  4087. ITypeInfo *CHqlExpression::queryRecordType()
  4088. {
  4089. return ::queryRecordType(queryType());
  4090. }
  4091. IHqlExpression *CHqlExpression::queryRecord()
  4092. {
  4093. ITypeInfo *t = queryRecordType();
  4094. if (t)
  4095. return queryExpression(t);
  4096. return NULL;
  4097. }
  4098. //== Commoning up code.... ==
  4099. void CHqlExpression::Link(void) const
  4100. {
  4101. #ifdef GATHER_LINK_STATS
  4102. numLinks++;
  4103. if (insideCreate)
  4104. numCreateLinks++;
  4105. #endif
  4106. Parent::Link();
  4107. CHECK_EXPR_SEQID(1);
  4108. }
  4109. bool CHqlExpression::Release(void) const
  4110. {
  4111. #ifdef GATHER_LINK_STATS
  4112. numReleases++;
  4113. if (insideCreate)
  4114. numCreateReleases++;
  4115. #endif
  4116. CHECK_EXPR_SEQID(2);
  4117. return Parent::Release();
  4118. }
  4119. void CHqlExpression::beforeDispose()
  4120. {
  4121. CHECK_EXPR_SEQID(3);
  4122. #ifdef CONSISTENCY_CHECK
  4123. if (hashcode)
  4124. {
  4125. unsigned oldhash = hashcode;
  4126. sethash();
  4127. assertex(hashcode == oldhash);
  4128. }
  4129. assertex(equals(*this));
  4130. #endif
  4131. if (infoFlags & HEFobserved)
  4132. {
  4133. CriticalBlock block(*exprCacheCS);
  4134. if (infoFlags & HEFobserved)
  4135. exprCache->removeExact(this);
  4136. }
  4137. assertex(!(infoFlags & HEFobserved));
  4138. }
  4139. unsigned CHqlExpression::getHash() const
  4140. {
  4141. return hashcode;
  4142. }
  4143. void CHqlExpression::addObserver(IObserver & observer)
  4144. {
  4145. assertex(!(infoFlags & HEFobserved));
  4146. assert(&observer == exprCache);
  4147. infoFlags |= HEFobserved;
  4148. }
  4149. void CHqlExpression::removeObserver(IObserver & observer)
  4150. {
  4151. assertex((infoFlags & HEFobserved));
  4152. assert(&observer == exprCache);
  4153. infoFlags &= ~HEFobserved;
  4154. }
  4155. IHqlExpression * CHqlExpression::commonUpExpression()
  4156. {
  4157. switch (op)
  4158. {
  4159. //I'm still not completely convinced that commoning up parameters doesn't cause problems.
  4160. //e.g. if a parameter from one function is passed into another. Don't common up for the moment....
  4161. //And parameter index must include all parameters in enclosing scopes as well.
  4162. case no_uncommoned_comma:
  4163. return this;
  4164. case no_service:
  4165. return this;
  4166. case no_privatescope:
  4167. case no_mergedscope:
  4168. return this;
  4169. case no_remotescope:
  4170. if (isAnnotation())
  4171. return this;
  4172. throwUnexpectedOp(op);
  4173. }
  4174. IHqlExpression * match;
  4175. {
  4176. CriticalBlock block(*exprCacheCS);
  4177. match = exprCache->addOrFind(*this);
  4178. #ifndef GATHER_COMMON_STATS
  4179. if (match == this)
  4180. return this;
  4181. #endif
  4182. match->Link();
  4183. if (!static_cast<CHqlExpression *>(match)->isAlive())
  4184. {
  4185. exprCache->replace(*this);
  4186. #ifndef GATHER_COMMON_STATS
  4187. return this;
  4188. #endif
  4189. Link();
  4190. match = this;
  4191. }
  4192. }
  4193. #ifdef GATHER_COMMON_STATS
  4194. node_operator statOp = op;
  4195. if (isAnnotation())
  4196. {
  4197. annotate_kind kind = getAnnotationKind();
  4198. commonUpAnnCount[kind]++;
  4199. if (match != this)
  4200. commonUpAnnClash[kind]++;
  4201. }
  4202. else
  4203. {
  4204. commonUpCount[statOp]++;
  4205. if (match != this)
  4206. commonUpClash[statOp]++;
  4207. }
  4208. #endif
  4209. Release();
  4210. return match;
  4211. }
  4212. IHqlExpression * CHqlExpression::calcNormalizedSelector() const
  4213. {
  4214. IHqlExpression * left = &operands.item(0);
  4215. IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
  4216. if ((normalizedLeft != left) || ((operands.ordinality() > 2) && hasAttribute(newAtom)))
  4217. {
  4218. HqlExprArray args;
  4219. appendArray(args, operands);
  4220. args.replace(*LINK(normalizedLeft), 0);
  4221. removeAttribute(args, newAtom);
  4222. return doCreateSelectExpr(args);
  4223. }
  4224. return NULL;
  4225. }
  4226. void displayHqlCacheStats()
  4227. {
  4228. #if 0
  4229. static HqlExprCopyArray prev;
  4230. DBGLOG("CachedItems = %d", exprCache->count());
  4231. exprCache->dumpStats();
  4232. JavaHashIteratorOf<IHqlExpression> iter(*exprCache, false);
  4233. ForEach(iter)
  4234. {
  4235. IHqlExpression & ret = iter.query();
  4236. if (!prev.contains(ret))
  4237. {
  4238. StringBuffer s;
  4239. processedTreeToECL(&ret, s);
  4240. DBGLOG("%p: %s", &ret, s.str());
  4241. }
  4242. }
  4243. prev.kill();
  4244. ForEach(iter)
  4245. {
  4246. prev.append(iter.query());
  4247. }
  4248. #endif
  4249. }
  4250. //--------------------------------------------------------------------------------------------------------------
  4251. CHqlExpressionWithType::CHqlExpressionWithType(node_operator _op, ITypeInfo * _type, HqlExprArray & _ownedOperands)
  4252. : CHqlExpressionWithTables(_op)
  4253. {
  4254. type = _type;
  4255. setOperands(_ownedOperands); // after type is initialized
  4256. }
  4257. CHqlExpressionWithType::~CHqlExpressionWithType()
  4258. {
  4259. ::Release(type);
  4260. }
  4261. ITypeInfo *CHqlExpressionWithType::queryType() const
  4262. {
  4263. return type;
  4264. }
  4265. ITypeInfo *CHqlExpressionWithType::getType()
  4266. {
  4267. ::Link(type);
  4268. return type;
  4269. }
  4270. CHqlExpression *CHqlExpressionWithType::makeExpression(node_operator _op, ITypeInfo *_type, HqlExprArray &_ownedOperands)
  4271. {
  4272. CHqlExpression *e = new CHqlExpressionWithType(_op, _type, _ownedOperands);
  4273. return (CHqlExpression *)e->closeExpr();
  4274. }
  4275. CHqlExpression *CHqlExpressionWithType::makeExpression(node_operator _op, ITypeInfo *_type, ...)
  4276. {
  4277. unsigned numArgs = 0;
  4278. va_list argscount;
  4279. va_start(argscount, _type);
  4280. for (;;)
  4281. {
  4282. IHqlExpression *parm = va_arg(argscount, IHqlExpression *);
  4283. if (!parm)
  4284. break;
  4285. numArgs++;
  4286. }
  4287. va_end(argscount);
  4288. HqlExprArray operands;
  4289. if (numArgs)
  4290. {
  4291. va_list args;
  4292. va_start(args, _type);
  4293. operands.ensure(numArgs);
  4294. for (;;)
  4295. {
  4296. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  4297. if (!parm)
  4298. break;
  4299. #ifdef _DEBUG
  4300. assertex(QUERYINTERFACE(parm, IHqlExpression));
  4301. #endif
  4302. operands.append(*parm);
  4303. }
  4304. va_end(args);
  4305. }
  4306. return makeExpression(_op, _type, operands);
  4307. }
  4308. IHqlExpression *CHqlExpressionWithType::clone(HqlExprArray &newkids)
  4309. {
  4310. if ((newkids.ordinality() == 0) && (operands.ordinality() == 0))
  4311. return LINK(this);
  4312. ITypeInfo * newType = NULL;
  4313. switch (op)
  4314. {
  4315. case no_outofline:
  4316. return createWrapper(op, newkids);
  4317. case no_embedbody:
  4318. {
  4319. if (queryType()->getTypeCode() == type_transform)
  4320. {
  4321. IHqlExpression & newRecord = newkids.item(1);
  4322. if (&newRecord != queryChild(1))
  4323. newType = makeTransformType(LINK(newRecord.queryType()));
  4324. }
  4325. break;
  4326. }
  4327. }
  4328. if (!newType)
  4329. newType = LINK(type);
  4330. return CHqlExpressionWithType::makeExpression(op, newType, newkids);
  4331. }
  4332. //--------------------------------------------------------------------------------------------------------------
  4333. CHqlNamedExpression::CHqlNamedExpression(node_operator _op, ITypeInfo *_type, IIdAtom * _id, ...) : CHqlExpressionWithType(_op, _type)
  4334. {
  4335. id = _id;
  4336. va_list args;
  4337. va_start(args, _id);
  4338. for (;;)
  4339. {
  4340. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  4341. if (!parm)
  4342. break;
  4343. #ifdef _DEBUG
  4344. assertex(QUERYINTERFACE(parm, IHqlExpression));
  4345. #endif
  4346. doAppendOperand(*parm);
  4347. }
  4348. va_end(args);
  4349. }
  4350. CHqlNamedExpression::CHqlNamedExpression(node_operator _op, ITypeInfo *_type, IIdAtom * _id, HqlExprArray &_ownedOperands) : CHqlExpressionWithType(_op, _type, _ownedOperands)
  4351. {
  4352. id = _id;
  4353. }
  4354. IHqlExpression *CHqlNamedExpression::clone(HqlExprArray &newkids)
  4355. {
  4356. if (op == no_funcdef)
  4357. return createFunctionDefinition(id, newkids);
  4358. return (new CHqlNamedExpression(op, getType(), id, newkids))->closeExpr();
  4359. }
  4360. bool CHqlNamedExpression::equals(const IHqlExpression & r) const
  4361. {
  4362. if (CHqlExpression::equals(r))
  4363. {
  4364. if (queryName() == r.queryName())
  4365. return true;
  4366. }
  4367. return false;
  4368. }
  4369. void CHqlNamedExpression::sethash()
  4370. {
  4371. CHqlExpression::sethash();
  4372. HASHFIELD(id);
  4373. }
  4374. IHqlExpression *createNamedValue(node_operator op, ITypeInfo *type, IIdAtom * id, HqlExprArray & args)
  4375. {
  4376. return (new CHqlNamedExpression(op, type, id, args))->closeExpr();
  4377. }
  4378. IHqlExpression *createId(IIdAtom * id)
  4379. {
  4380. HqlExprArray args;
  4381. return createNamedValue(no_id, makeNullType(), id, args);
  4382. }
  4383. //--------------------------------------------------------------------------------------------------------------
  4384. inline void addUniqueTable(HqlExprCopyArray & array, IHqlExpression * ds)
  4385. {
  4386. if (array.find(*ds) == NotFound)
  4387. array.append(*ds);
  4388. }
  4389. inline void addHiddenTable(HqlExprCopyArray & array, IHqlExpression * ds, IHqlExpression * selSeq)
  4390. {
  4391. #if defined(GATHER_HIDDEN_SELECTORS)
  4392. if (array.find(*ds) == NotFound)
  4393. array.append(*ds);
  4394. #endif
  4395. }
  4396. inline void addActiveTable(HqlExprCopyArray & array, IHqlExpression * ds)
  4397. {
  4398. //left.subfield should be reduced the base cursor
  4399. ds = queryDatasetCursor(ds);
  4400. // This test is valid once the tree is normalized, but now this can be called on a parse tree.
  4401. // assertex(ds == ds->queryNormalizedSelector());
  4402. node_operator dsOp = ds->getOperator();
  4403. if (dsOp != no_self && dsOp != no_selfref)
  4404. addUniqueTable(array, ds->queryNormalizedSelector());
  4405. }
  4406. //---------------------------------------------------------------------------------------------------------------------
  4407. CUsedTables::CUsedTables()
  4408. {
  4409. tables.single = NULL;
  4410. numTables = 0;
  4411. numActiveTables = 0;
  4412. }
  4413. CUsedTables::~CUsedTables()
  4414. {
  4415. if (numTables > 1)
  4416. delete [] tables.multi;
  4417. }
  4418. bool CUsedTables::usesSelector(IHqlExpression * selector) const
  4419. {
  4420. if (numTables > 1)
  4421. {
  4422. for (unsigned i=0; i < numActiveTables; i++)
  4423. {
  4424. if (tables.multi[i] == selector)
  4425. return true;
  4426. }
  4427. return false;
  4428. }
  4429. //Following works if numTables == 0
  4430. return (selector == tables.single);
  4431. }
  4432. void CUsedTables::gatherTablesUsed(CUsedTablesBuilder & used) const
  4433. {
  4434. if (numTables == 0)
  4435. return;
  4436. if (numTables == 1)
  4437. {
  4438. if (numActiveTables == 1)
  4439. used.addActiveTable(tables.single);
  4440. else
  4441. used.addNewTable(tables.single);
  4442. }
  4443. else
  4444. {
  4445. for (unsigned i1=0; i1 < numActiveTables; i1++)
  4446. used.addActiveTable(tables.multi[i1]);
  4447. for (unsigned i2=numActiveTables; i2 < numTables; i2++)
  4448. used.addNewTable(tables.multi[i2]);
  4449. }
  4450. }
  4451. void CUsedTables::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope) const
  4452. {
  4453. if (numTables == 0)
  4454. return;
  4455. if (numTables == 1)
  4456. {
  4457. if (numActiveTables == 1)
  4458. {
  4459. if (inScope)
  4460. addUniqueTable(*inScope, tables.single);
  4461. }
  4462. else
  4463. {
  4464. if (newScope)
  4465. addUniqueTable(*newScope, tables.single);
  4466. }
  4467. }
  4468. else
  4469. {
  4470. if (inScope)
  4471. {
  4472. for (unsigned i1=0; i1 < numActiveTables; i1++)
  4473. addUniqueTable(*inScope, tables.multi[i1]);
  4474. }
  4475. if (newScope)
  4476. {
  4477. for (unsigned i2=numActiveTables; i2 < numTables; i2++)
  4478. addUniqueTable(*newScope, tables.multi[i2]);
  4479. }
  4480. }
  4481. }
  4482. void CUsedTables::set(HqlExprCopyArray & activeTables, HqlExprCopyArray & newTables)
  4483. {
  4484. numActiveTables = activeTables.ordinality();
  4485. numTables = numActiveTables + newTables.ordinality();
  4486. if (numTables == 1)
  4487. {
  4488. if (numActiveTables == 1)
  4489. {
  4490. tables.single = &activeTables.item(0);
  4491. }
  4492. else
  4493. {
  4494. tables.single = &newTables.item(0);
  4495. }
  4496. }
  4497. else if (numTables != 0)
  4498. {
  4499. IHqlExpression * * multi = new IHqlExpression * [numTables];
  4500. for (unsigned i1=0; i1 < numActiveTables; i1++)
  4501. multi[i1] = &activeTables.item(i1);
  4502. for (unsigned i2=numActiveTables; i2 < numTables; i2++)
  4503. multi[i2] = &newTables.item(i2-numActiveTables);
  4504. tables.multi = multi;
  4505. }
  4506. }
  4507. void CUsedTables::setActiveTable(IHqlExpression * expr)
  4508. {
  4509. tables.single = expr;
  4510. numTables = 1;
  4511. numActiveTables = 1;
  4512. }
  4513. //---------------------------------------------------------------------------------------------------------------------
  4514. void CUsedTablesBuilder::addNewTable(IHqlExpression * expr)
  4515. {
  4516. addUniqueTable(newScopeTables, expr);
  4517. }
  4518. void CUsedTablesBuilder::addHiddenTable(IHqlExpression * expr, IHqlExpression * selSeq)
  4519. {
  4520. ::addHiddenTable(newScopeTables, expr, selSeq);
  4521. }
  4522. void CUsedTablesBuilder::addActiveTable(IHqlExpression * expr)
  4523. {
  4524. ::addActiveTable(inScopeTables, expr);
  4525. }
  4526. void CUsedTablesBuilder::cleanupProduction()
  4527. {
  4528. ForEachItemInRev(i, inScopeTables)
  4529. {
  4530. switch (inScopeTables.item(i).getOperator())
  4531. {
  4532. case no_matchattr:
  4533. case no_matchrow:
  4534. inScopeTables.remove(i);
  4535. break;
  4536. }
  4537. }
  4538. }
  4539. void CUsedTablesBuilder::removeParent(IHqlExpression * expr)
  4540. {
  4541. IHqlExpression * sel = expr->queryNormalizedSelector();
  4542. removeActive(sel);
  4543. loop
  4544. {
  4545. IHqlExpression * root = queryRoot(expr);
  4546. if (!root || root->getOperator() != no_select)
  4547. break;
  4548. if (!root->hasAttribute(newAtom))
  4549. break;
  4550. expr = root->queryChild(0);
  4551. removeActive(expr->queryNormalizedSelector());
  4552. }
  4553. }
  4554. void CUsedTablesBuilder::removeActiveRecords()
  4555. {
  4556. ForEachItemInRev(i, inScopeTables)
  4557. {
  4558. if (inScopeTables.item(i).isRecord())
  4559. inScopeTables.remove(i);
  4560. }
  4561. }
  4562. void CUsedTablesBuilder::removeRows(IHqlExpression * expr, IHqlExpression * left, IHqlExpression * right)
  4563. {
  4564. node_operator rowsSide = queryHasRows(expr);
  4565. if (rowsSide == no_none)
  4566. return;
  4567. IHqlExpression * rowsid = expr->queryAttribute(_rowsid_Atom);
  4568. switch (rowsSide)
  4569. {
  4570. case no_left:
  4571. {
  4572. OwnedHqlExpr rowsExpr = createDataset(no_rows, LINK(left), LINK(rowsid));
  4573. inScopeTables.zap(*rowsExpr);
  4574. break;
  4575. }
  4576. case no_right:
  4577. {
  4578. OwnedHqlExpr rowsExpr = createDataset(no_rows, LINK(right), LINK(rowsid));
  4579. inScopeTables.zap(*rowsExpr);
  4580. break;
  4581. }
  4582. default:
  4583. throwUnexpectedOp(rowsSide);
  4584. }
  4585. }
  4586. //---------------------------------------------------------------------------------------------------------------------
  4587. //Don't need to check if already visited, because the information is cached in the expression itself.
  4588. void CHqlExpressionWithTables::cacheChildrenTablesUsed(CUsedTablesBuilder & used, unsigned from, unsigned to)
  4589. {
  4590. for (unsigned i=from; i < to; i++)
  4591. queryChild(i)->gatherTablesUsed(used);
  4592. }
  4593. void CHqlExpressionWithTables::cacheInheritChildTablesUsed(IHqlExpression * ds, CUsedTablesBuilder & used, const HqlExprCopyArray & childInScopeTables)
  4594. {
  4595. //The argument to the operator is a new table, don't inherit grandchildren
  4596. used.addNewTable(ds);
  4597. //Any datasets in that are referenced by the child are included, but not including
  4598. //the dataset itself.
  4599. IHqlExpression * normalizedDs = ds->queryNormalizedSelector();
  4600. ForEachItemIn(idx, childInScopeTables)
  4601. {
  4602. IHqlExpression & cur = childInScopeTables.item(idx);
  4603. if (&cur != normalizedDs)
  4604. used.addActiveTable(&cur);
  4605. }
  4606. }
  4607. void CHqlExpressionWithTables::cacheTableUseage(CUsedTablesBuilder & used, IHqlExpression * expr)
  4608. {
  4609. #ifdef GATHER_HIDDEN_SELECTORS
  4610. expr->gatherTablesUsed(used);
  4611. #else
  4612. if (expr->getOperator() == no_activerow)
  4613. used.addActiveTable(expr->queryChild(0));
  4614. else
  4615. {
  4616. HqlExprCopyArray childInScopeTables;
  4617. expr->gatherTablesUsed(NULL, &childInScopeTables);
  4618. //The argument to the operator is a new table, don't inherit grandchildren
  4619. cacheInheritChildTablesUsed(expr, used, childInScopeTables);
  4620. }
  4621. #endif
  4622. }
  4623. void CHqlExpressionWithTables::cachePotentialTablesUsed(CUsedTablesBuilder & used)
  4624. {
  4625. ForEachChild(i, this)
  4626. {
  4627. IHqlExpression * cur = queryChild(i);
  4628. if (cur->isDataset())
  4629. cacheTableUseage(used, cur);
  4630. else
  4631. cur->gatherTablesUsed(used);
  4632. }
  4633. }
  4634. void CHqlExpressionWithTables::cacheTablesProcessChildScope(CUsedTablesBuilder & used, bool ignoreInputs)
  4635. {
  4636. unsigned max = numChildren();
  4637. switch (getChildDatasetType(this))
  4638. {
  4639. case childdataset_none:
  4640. cacheChildrenTablesUsed(used, 0, max);
  4641. break;
  4642. case childdataset_many_noscope:
  4643. if (ignoreInputs)
  4644. {
  4645. unsigned first = getFirstActivityArgument(this);
  4646. unsigned last = first + getNumActivityArguments(this);
  4647. cacheChildrenTablesUsed(used, 0, first);
  4648. cacheChildrenTablesUsed(used, last, max);
  4649. }
  4650. else
  4651. cacheChildrenTablesUsed(used, 0, max);
  4652. break;
  4653. case childdataset_dataset_noscope:
  4654. if (ignoreInputs)
  4655. cacheChildrenTablesUsed(used, 1, max);
  4656. else
  4657. cacheChildrenTablesUsed(used, 0, max);
  4658. break;
  4659. case childdataset_if:
  4660. if (ignoreInputs)
  4661. cacheChildrenTablesUsed(used, 0, 1);
  4662. else
  4663. cacheChildrenTablesUsed(used, 0, max);
  4664. break;
  4665. case childdataset_case:
  4666. case childdataset_map:
  4667. //Assume the worst
  4668. cacheChildrenTablesUsed(used, 0, max);
  4669. break;
  4670. case childdataset_many:
  4671. {
  4672. //can now have sorted() attribute which is dependent on the no_activetable element.
  4673. unsigned firstAttr = getNumChildTables(this);
  4674. cacheChildrenTablesUsed(used, firstAttr, max);
  4675. used.removeActive(queryActiveTableSelector());
  4676. if (!ignoreInputs)
  4677. cacheChildrenTablesUsed(used, 0, firstAttr);
  4678. break;
  4679. }
  4680. case childdataset_dataset:
  4681. {
  4682. IHqlExpression * ds = queryChild(0);
  4683. cacheChildrenTablesUsed(used, 1, max);
  4684. used.removeParent(ds);
  4685. if (!ignoreInputs)
  4686. cacheChildrenTablesUsed(used, 0, 1);
  4687. }
  4688. break;
  4689. case childdataset_datasetleft:
  4690. {
  4691. IHqlExpression * ds = queryChild(0);
  4692. IHqlExpression * selSeq = querySelSeq(this);
  4693. OwnedHqlExpr left = createSelector(no_left, ds, selSeq);
  4694. cacheChildrenTablesUsed(used, 1, max);
  4695. used.removeActive(left);
  4696. used.removeParent(ds);
  4697. used.removeRows(this, left, NULL);
  4698. switch (op)
  4699. {
  4700. case no_parse:
  4701. case no_newparse:
  4702. used.cleanupProduction();
  4703. used.removeActive(queryNlpParsePseudoTable());
  4704. break;
  4705. case no_xmlparse:
  4706. case no_newxmlparse:
  4707. used.removeActive(queryXmlParsePseudoTable());
  4708. break;
  4709. }
  4710. if (!ignoreInputs)
  4711. cacheChildrenTablesUsed(used, 0, 1);
  4712. #ifdef GATHER_HIDDEN_SELECTORS
  4713. used.addHiddenTable(left, selSeq);
  4714. #endif
  4715. break;
  4716. }
  4717. case childdataset_left:
  4718. {
  4719. IHqlExpression * ds = queryChild(0);
  4720. IHqlExpression * selSeq = querySelSeq(this);
  4721. OwnedHqlExpr left = createSelector(no_left, ds, selSeq);
  4722. cacheChildrenTablesUsed(used, 1, max);
  4723. used.removeActive(left);
  4724. used.removeRows(this, left, NULL);
  4725. if (!ignoreInputs)
  4726. cacheChildrenTablesUsed(used, 0, 1);
  4727. #ifdef GATHER_HIDDEN_SELECTORS
  4728. used.addHiddenTable(left, selSeq);
  4729. #endif
  4730. break;
  4731. }
  4732. case childdataset_same_left_right:
  4733. case childdataset_nway_left_right:
  4734. {
  4735. IHqlExpression * ds = queryChild(0);
  4736. IHqlExpression * selSeq = querySelSeq(this);
  4737. OwnedHqlExpr left = createSelector(no_left, ds, selSeq);
  4738. OwnedHqlExpr right = createSelector(no_right, ds, selSeq);
  4739. cacheChildrenTablesUsed(used, 1, max);
  4740. used.removeActive(left);
  4741. used.removeActive(right);
  4742. used.removeRows(this, left, right);
  4743. if (!ignoreInputs)
  4744. cacheChildrenTablesUsed(used, 0, 1);
  4745. #ifdef GATHER_HIDDEN_SELECTORS
  4746. used.addHiddenTable(left, selSeq);
  4747. used.addHiddenTable(right, selSeq);
  4748. #endif
  4749. break;
  4750. }
  4751. case childdataset_top_left_right:
  4752. {
  4753. IHqlExpression * ds = queryChild(0);
  4754. IHqlExpression * selSeq = querySelSeq(this);
  4755. OwnedHqlExpr left = createSelector(no_left, ds, selSeq);
  4756. OwnedHqlExpr right = createSelector(no_right, ds, selSeq);
  4757. cacheChildrenTablesUsed(used, 1, max);
  4758. used.removeParent(ds);
  4759. used.removeActive(left);
  4760. used.removeActive(right);
  4761. used.removeRows(this, left, right);
  4762. cacheChildrenTablesUsed(used, 0, 1);
  4763. #ifdef GATHER_HIDDEN_SELECTORS
  4764. used.addHiddenTable(left, selSeq);
  4765. used.addHiddenTable(right, selSeq);
  4766. #endif
  4767. break;
  4768. }
  4769. case childdataset_leftright:
  4770. {
  4771. IHqlExpression * leftDs = queryChild(0);
  4772. IHqlExpression * rightDs = queryChild(1);
  4773. IHqlExpression * selSeq = querySelSeq(this);
  4774. OwnedHqlExpr left = createSelector(no_left, leftDs, selSeq);
  4775. OwnedHqlExpr right = createSelector(no_right, rightDs, selSeq);
  4776. cacheChildrenTablesUsed(used, 2, max);
  4777. used.removeActive(right);
  4778. used.removeRows(this, left, right);
  4779. if (op == no_normalize)
  4780. {
  4781. //two datasets form of normalize is weird because right dataset is based on left
  4782. cacheChildrenTablesUsed(used, 1, 2);
  4783. used.removeActive(left);
  4784. if (!ignoreInputs)
  4785. cacheChildrenTablesUsed(used, 0, 1);
  4786. }
  4787. else
  4788. {
  4789. used.removeActive(left);
  4790. if (!ignoreInputs)
  4791. cacheChildrenTablesUsed(used, 0, 2);
  4792. }
  4793. #ifdef GATHER_HIDDEN_SELECTORS
  4794. used.addHiddenTable(left, selSeq);
  4795. used.addHiddenTable(right, selSeq);
  4796. #endif
  4797. break;
  4798. }
  4799. break;
  4800. case childdataset_evaluate:
  4801. //handled elsewhere...
  4802. default:
  4803. UNIMPLEMENTED;
  4804. }
  4805. }
  4806. void CHqlExpressionWithTables::calcTablesUsed(CUsedTablesBuilder & used, bool ignoreInputs)
  4807. {
  4808. switch (op)
  4809. {
  4810. case no_attr:
  4811. case no_attr_link:
  4812. case no_keyed:
  4813. case no_colon:
  4814. case no_cluster:
  4815. case no_nameof:
  4816. case no_translated:
  4817. case no_constant:
  4818. break;
  4819. case no_select:
  4820. {
  4821. IHqlExpression * ds = queryChild(0);
  4822. if (isSelectRootAndActive())
  4823. {
  4824. used.addActiveTable(ds);
  4825. }
  4826. else
  4827. {
  4828. ds->gatherTablesUsed(used);
  4829. }
  4830. break;
  4831. }
  4832. case no_activerow:
  4833. used.addActiveTable(queryChild(0));
  4834. break;
  4835. case no_rows:
  4836. case no_rowset:
  4837. //MORE: This is a bit strange!
  4838. used.addActiveTable(queryChild(0));
  4839. break;
  4840. case no_left:
  4841. case no_right:
  4842. used.addActiveTable(this);
  4843. break;
  4844. case no_counter:
  4845. //NB: Counter is added as a pseudo table, because it is too hard to keep track of nested counters otherwise
  4846. used.addActiveTable(this);
  4847. break;
  4848. case no_filepos:
  4849. case no_file_logicalname:
  4850. used.addActiveTable(queryChild(0));
  4851. break;
  4852. case NO_AGGREGATE:
  4853. case no_createset:
  4854. {
  4855. #ifdef GATHER_HIDDEN_SELECTORS
  4856. cachePotentialTablesUsed(used);
  4857. used.removeParent(queryChild(0));
  4858. #else
  4859. HqlExprCopyArray childInScopeTables;
  4860. ForEachChild(idx, this)
  4861. queryChild(idx)->gatherTablesUsed(NULL, &childInScopeTables);
  4862. //The argument to the operator is a new table, don't inherit grandchildren
  4863. IHqlExpression * ds = queryChild(0);
  4864. cacheInheritChildTablesUsed(ds, used, childInScopeTables);
  4865. #endif
  4866. }
  4867. break;
  4868. case no_sizeof:
  4869. cachePotentialTablesUsed(used);
  4870. used.removeActive(queryActiveTableSelector());
  4871. used.removeActiveRecords();
  4872. break;
  4873. case no_externalcall:
  4874. case no_rowvalue:
  4875. case no_offsetof:
  4876. case no_eq:
  4877. case no_ne:
  4878. case no_lt:
  4879. case no_le:
  4880. case no_gt:
  4881. case no_ge:
  4882. case no_order:
  4883. case no_assign:
  4884. case no_call:
  4885. case no_libraryscopeinstance:
  4886. //MORE: Should check this doesn't make the comparison invalid.
  4887. cachePotentialTablesUsed(used);
  4888. break;
  4889. case no_keyindex:
  4890. case no_newkeyindex:
  4891. cacheChildrenTablesUsed(used, 1, numChildren());
  4892. used.removeParent(queryChild(0));
  4893. //Distributed attribute might contain references to the no_activetable
  4894. used.removeActive(queryActiveTableSelector());
  4895. break;
  4896. case no_evaluate:
  4897. cacheTableUseage(used, queryChild(0));
  4898. queryChild(1)->gatherTablesUsed(used);
  4899. break;
  4900. case no_table:
  4901. {
  4902. cacheChildrenTablesUsed(used, 0, numChildren());
  4903. IHqlExpression * parent = queryChild(3);
  4904. if (parent)
  4905. used.removeParent(parent);
  4906. break;
  4907. }
  4908. case no_pat_production:
  4909. {
  4910. cacheChildrenTablesUsed(used, 0, numChildren());
  4911. used.cleanupProduction();
  4912. break;
  4913. }
  4914. default:
  4915. {
  4916. ITypeInfo * thisType = queryType();
  4917. unsigned max = numChildren();
  4918. if (max)
  4919. {
  4920. if (thisType)
  4921. {
  4922. switch (thisType->getTypeCode())
  4923. {
  4924. case type_void:
  4925. case type_dictionary:
  4926. case type_table:
  4927. case type_groupedtable:
  4928. case type_row:
  4929. case type_transform:
  4930. {
  4931. cacheTablesProcessChildScope(used, ignoreInputs);
  4932. IHqlExpression * counter = queryAttribute(_countProject_Atom);
  4933. if (counter)
  4934. used.removeActive(counter->queryChild(0));
  4935. break;
  4936. }
  4937. default:
  4938. cacheChildrenTablesUsed(used, 0, max);
  4939. break;
  4940. }
  4941. }
  4942. else
  4943. cacheChildrenTablesUsed(used, 0, max);
  4944. }
  4945. break;
  4946. }
  4947. }
  4948. switch (op)
  4949. {
  4950. case no_xmltext:
  4951. case no_xmlunicode:
  4952. case no_xmlproject:
  4953. used.addActiveTable(queryXmlParsePseudoTable());
  4954. break;
  4955. case no_matched:
  4956. case no_matchtext:
  4957. case no_matchunicode:
  4958. case no_matchlength:
  4959. case no_matchposition:
  4960. case no_matchrow:
  4961. case no_matchutf8:
  4962. case no_matchattr:
  4963. used.addActiveTable(queryNlpParsePseudoTable());
  4964. break;
  4965. case no_externalcall:
  4966. {
  4967. IHqlExpression * def = queryExternalDefinition()->queryChild(0);
  4968. if (def->hasAttribute(userMatchFunctionAtom))
  4969. used.addActiveTable(queryNlpParsePseudoTable());
  4970. break;
  4971. }
  4972. }
  4973. }
  4974. void CHqlExpressionWithTables::cacheTablesUsed()
  4975. {
  4976. if (!(infoFlags & HEFgatheredNew))
  4977. {
  4978. //NB: This is not thread safe! Should be protected with a cs
  4979. //but actually want it to be more efficient than that - don't want to call a cs at each level.
  4980. //So need an ensureCached() function surrounding it that is cs protected.
  4981. //Special case some common operators that can avoid going through the general code
  4982. bool specialCased = false;
  4983. if (false)
  4984. switch (op)
  4985. {
  4986. case no_attr:
  4987. case no_attr_link:
  4988. case no_keyed:
  4989. case no_colon:
  4990. case no_cluster:
  4991. case no_nameof:
  4992. case no_translated:
  4993. case no_constant:
  4994. break;
  4995. case no_select:
  4996. {
  4997. IHqlExpression * ds = queryChild(0);
  4998. if (isSelectRootAndActive())
  4999. {
  5000. usedTables.setActiveTable(ds);
  5001. }
  5002. else
  5003. {
  5004. //MORE: ds->gatherTablesUsed(usedTables);
  5005. //which could ideally clone
  5006. specialCased = false;
  5007. }
  5008. break;
  5009. }
  5010. case no_activerow:
  5011. usedTables.setActiveTable(queryChild(0));
  5012. break;
  5013. case no_rows:
  5014. case no_rowset:
  5015. //MORE: This is a bit strange!
  5016. usedTables.setActiveTable(queryChild(0));
  5017. break;
  5018. case no_left:
  5019. case no_right:
  5020. usedTables.setActiveTable(this);
  5021. break;
  5022. case no_counter:
  5023. //NB: Counter is added as a pseudo table, because it is too hard to keep track of nested counters otherwise
  5024. usedTables.setActiveTable(this);
  5025. break;
  5026. case no_filepos:
  5027. case no_file_logicalname:
  5028. usedTables.setActiveTable(queryChild(0));
  5029. break;
  5030. default:
  5031. specialCased = false;
  5032. break;
  5033. }
  5034. if (!specialCased)
  5035. {
  5036. CUsedTablesBuilder used;
  5037. calcTablesUsed(used, false);
  5038. used.set(usedTables);
  5039. }
  5040. infoFlags |= HEFgatheredNew;
  5041. }
  5042. }
  5043. bool CHqlExpressionWithTables::isIndependentOfScope()
  5044. {
  5045. cacheTablesUsed();
  5046. return usedTables.isIndependentOfScope();
  5047. }
  5048. bool CHqlExpressionWithTables::isIndependentOfScopeIgnoringInputs()
  5049. {
  5050. CUsedTablesBuilder used;
  5051. //MORE: We could try using a flag set by cacheTablesUsed() instead
  5052. calcTablesUsed(used, true);
  5053. return used.isIndependentOfScope();
  5054. }
  5055. bool CHqlExpressionWithTables::usesSelector(IHqlExpression * selector)
  5056. {
  5057. cacheTablesUsed();
  5058. return usedTables.usesSelector(selector);
  5059. }
  5060. void CHqlExpressionWithTables::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope)
  5061. {
  5062. cacheTablesUsed();
  5063. usedTables.gatherTablesUsed(newScope, inScope);
  5064. }
  5065. void CHqlExpressionWithTables::gatherTablesUsed(CUsedTablesBuilder & used)
  5066. {
  5067. cacheTablesUsed();
  5068. usedTables.gatherTablesUsed(used);
  5069. }
  5070. //==============================================================================================================
  5071. CHqlSelectBaseExpression::CHqlSelectBaseExpression()
  5072. : CHqlExpression(no_select)
  5073. {
  5074. }
  5075. ITypeInfo *CHqlSelectBaseExpression::queryType() const
  5076. {
  5077. dbgassertex(operands.ordinality()>=2);
  5078. return operands.item(1).queryType();
  5079. }
  5080. ITypeInfo *CHqlSelectBaseExpression::getType()
  5081. {
  5082. dbgassertex(operands.ordinality()>=2);
  5083. return operands.item(1).getType();
  5084. }
  5085. void CHqlSelectBaseExpression::setOperands(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr)
  5086. {
  5087. //Need to be very careful about the order that this is done in, since queryType() depends on operand2
  5088. unsigned max = attr ? 3 : 2;
  5089. operands.ensure(max);
  5090. operands.append(*left);
  5091. operands.append(*right);
  5092. if (attr)
  5093. operands.append(*attr);
  5094. //Now the operands are added we can call the functions to update the flags
  5095. for (unsigned i=0; i < max; i++)
  5096. onAppendOperand(operands.item(i), i);
  5097. }
  5098. void CHqlSelectBaseExpression::setOperands(HqlExprArray & _ownedOperands)
  5099. {
  5100. //base setOperands() already processes things in the correct order
  5101. CHqlExpression::setOperands(_ownedOperands);
  5102. }
  5103. IHqlExpression * CHqlSelectBaseExpression::clone(HqlExprArray &newkids)
  5104. {
  5105. return createSelectExpr(newkids);
  5106. }
  5107. IHqlExpression * CHqlSelectBaseExpression::makeSelectExpression(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr)
  5108. {
  5109. #ifdef _DEBUG
  5110. assertex(!right->isDataset());
  5111. assertex(left->getOperator() != no_activerow);
  5112. #endif
  5113. IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
  5114. bool needNormalize = (normalizedLeft != left) || (attr && attr->queryName() == newAtom);
  5115. CHqlSelectBaseExpression * select;
  5116. if (needNormalize)
  5117. select = new CHqlSelectExpression;
  5118. else
  5119. select = new CHqlNormalizedSelectExpression;
  5120. select->setOperands(left, right, attr);
  5121. select->calcNormalized();
  5122. return select->closeExpr();
  5123. }
  5124. IHqlExpression * CHqlSelectBaseExpression::makeSelectExpression(HqlExprArray & ownedOperands)
  5125. {
  5126. #ifdef _DEBUG
  5127. assertex(!ownedOperands.item(1).isDataset());
  5128. assertex(ownedOperands.item(0).getOperator() != no_activerow);
  5129. #endif
  5130. IHqlExpression * left = &ownedOperands.item(0);
  5131. IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
  5132. bool needNormalize = (normalizedLeft != left) || ((ownedOperands.ordinality() > 2) && ::hasAttribute(newAtom, ownedOperands));
  5133. CHqlSelectBaseExpression * select;
  5134. if (needNormalize)
  5135. select = new CHqlSelectExpression;
  5136. else
  5137. select = new CHqlNormalizedSelectExpression;
  5138. select->setOperands(ownedOperands);
  5139. select->calcNormalized();
  5140. return select->closeExpr();
  5141. }
  5142. bool CHqlSelectBaseExpression::isIndependentOfScope()
  5143. {
  5144. if (isSelectRootAndActive())
  5145. {
  5146. return false;
  5147. }
  5148. else
  5149. {
  5150. IHqlExpression * ds = queryChild(0);
  5151. return ds->isIndependentOfScope();
  5152. }
  5153. }
  5154. bool CHqlSelectBaseExpression::isIndependentOfScopeIgnoringInputs()
  5155. {
  5156. if (isSelectRootAndActive())
  5157. {
  5158. return false;
  5159. }
  5160. else
  5161. {
  5162. IHqlExpression * ds = queryChild(0);
  5163. return ds->isIndependentOfScopeIgnoringInputs();
  5164. }
  5165. }
  5166. bool CHqlSelectBaseExpression::usesSelector(IHqlExpression * selector)
  5167. {
  5168. IHqlExpression * ds = queryChild(0);
  5169. if (isSelectRootAndActive())
  5170. {
  5171. return (selector == ds);
  5172. }
  5173. else
  5174. {
  5175. return ds->usesSelector(selector);
  5176. }
  5177. }
  5178. void CHqlSelectBaseExpression::gatherTablesUsed(CUsedTablesBuilder & used)
  5179. {
  5180. IHqlExpression * ds = queryChild(0);
  5181. if (isSelectRootAndActive())
  5182. {
  5183. used.addActiveTable(ds);
  5184. }
  5185. else
  5186. {
  5187. ds->gatherTablesUsed(used);
  5188. }
  5189. }
  5190. void CHqlSelectBaseExpression::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope)
  5191. {
  5192. IHqlExpression * ds = queryChild(0);
  5193. if (isSelectRootAndActive())
  5194. {
  5195. if (inScope)
  5196. ::addActiveTable(*inScope, ds);
  5197. }
  5198. else
  5199. {
  5200. ds->gatherTablesUsed(newScope, inScope);
  5201. }
  5202. }
  5203. //==============================================================================================================
  5204. IHqlExpression * CHqlNormalizedSelectExpression::queryNormalizedSelector(bool skipIndex)
  5205. {
  5206. return this;
  5207. }
  5208. void CHqlNormalizedSelectExpression::calcNormalized()
  5209. {
  5210. #ifdef VERIFY_EXPR_INTEGRITY
  5211. OwnedHqlExpr normalized = calcNormalizedSelector();
  5212. assertex(!normalized);
  5213. #endif
  5214. }
  5215. IHqlExpression * CHqlSelectExpression::queryNormalizedSelector(bool skipIndex)
  5216. {
  5217. if (normalized)
  5218. return normalized;
  5219. return this;
  5220. }
  5221. void CHqlSelectExpression::calcNormalized()
  5222. {
  5223. normalized.setown(calcNormalizedSelector());
  5224. assertex(normalized);
  5225. }
  5226. //==============================================================================================================
  5227. CHqlConstant::CHqlConstant(IValue *_val) : CHqlExpression(no_constant)
  5228. {
  5229. val = _val;
  5230. infoFlags |= (HEFhasunadorned|HEFgatheredNew);
  5231. }
  5232. CHqlConstant *CHqlConstant::makeConstant(IValue *_val)
  5233. {
  5234. CHqlConstant *e = new CHqlConstant(_val);
  5235. return (CHqlConstant *) e->closeExpr();
  5236. }
  5237. bool CHqlConstant::equals(const IHqlExpression & other) const
  5238. {
  5239. if (!isAlive()) return false;
  5240. IValue * oval = other.queryValue();
  5241. if (oval)
  5242. if (val->queryType() == oval->queryType())
  5243. if (oval->compare(val) == 0)
  5244. return true;
  5245. return false;
  5246. }
  5247. void CHqlConstant::sethash()
  5248. {
  5249. CHqlExpression::sethash();
  5250. hashcode = val->getHash(hashcode);
  5251. }
  5252. IHqlExpression *CHqlConstant::clone(HqlExprArray &newkids)
  5253. {
  5254. assertex(newkids.ordinality() == 0);
  5255. Link();
  5256. return this;
  5257. }
  5258. CHqlConstant::~CHqlConstant()
  5259. {
  5260. val->Release();
  5261. }
  5262. StringBuffer &CHqlConstant::toString(StringBuffer &ret)
  5263. {
  5264. val->generateECL(ret);
  5265. return ret;
  5266. }
  5267. ITypeInfo *CHqlConstant::queryType() const
  5268. {
  5269. return val->queryType();
  5270. }
  5271. ITypeInfo *CHqlConstant::getType()
  5272. {
  5273. return LINK(val->queryType());
  5274. }
  5275. //==============================================================================================================
  5276. CHqlField::CHqlField(IIdAtom * _id, ITypeInfo *_type, IHqlExpression *defvalue)
  5277. : CHqlExpressionWithType(no_field, _type)
  5278. {
  5279. appendOperands(defvalue, NULL);
  5280. assertex(_id);
  5281. id = _id;
  5282. onCreateField();
  5283. }
  5284. CHqlField::CHqlField(IIdAtom * _id, ITypeInfo *_type, HqlExprArray &_ownedOperands)
  5285. : CHqlExpressionWithType(no_field, _type, _ownedOperands)
  5286. {
  5287. assertex(_id);
  5288. id = _id;
  5289. onCreateField();
  5290. }
  5291. void CHqlField::onCreateField()
  5292. {
  5293. bool hasLCA = hasAttribute(_linkCounted_Atom);
  5294. ITypeInfo * newType = setLinkCountedAttr(type, hasLCA);
  5295. type->Release();
  5296. type = newType;
  5297. #ifdef _DEBUG
  5298. if (hasLinkCountedModifier(type) != hasAttribute(_linkCounted_Atom))
  5299. throwUnexpected();
  5300. #endif
  5301. #ifdef DEBUG_ON_CREATE
  5302. if (queryName() == createIdAtom("imgLength"))
  5303. PrintLog("Create field %s=%p", expr->queryName()->str(), expr);
  5304. #endif
  5305. infoFlags &= ~(HEFfunctionOfGroupAggregate);
  5306. infoFlags |= HEFcontextDependentException;
  5307. assertex(type->getTypeCode() != type_record);
  5308. IHqlExpression * typeExpr = NULL;
  5309. switch (type->getTypeCode())
  5310. {
  5311. case type_alien:
  5312. typeExpr = queryExpression(type);
  5313. break;
  5314. case type_row:
  5315. break;
  5316. case type_dictionary:
  5317. case type_table:
  5318. case type_groupedtable:
  5319. typeExpr = queryRecord();
  5320. #ifdef _DEBUG
  5321. assertex(!recordRequiresLinkCount(typeExpr) || hasAttribute(_linkCounted_Atom));
  5322. #endif
  5323. break;
  5324. }
  5325. if (typeExpr)
  5326. {
  5327. infoFlags |= (typeExpr->getInfoFlags() & HEFalwaysInherit);
  5328. infoFlags2 |= (typeExpr->getInfoFlags2() & HEF2alwaysInherit);
  5329. }
  5330. }
  5331. bool CHqlField::equals(const IHqlExpression & r) const
  5332. {
  5333. if (CHqlExpression::equals(r))
  5334. {
  5335. const CHqlField *fr = QUERYINTERFACE(&r, const CHqlField);
  5336. if (fr && fr->id==id)
  5337. return true;
  5338. }
  5339. return false;
  5340. }
  5341. IHqlExpression *CHqlField::clone(HqlExprArray &newkids)
  5342. {
  5343. CHqlField* e = new CHqlField(id, LINK(type), newkids);
  5344. return e->closeExpr();
  5345. }
  5346. StringBuffer &CHqlField::toString(StringBuffer &ret)
  5347. {
  5348. ret.append(id->str());
  5349. return ret;
  5350. }
  5351. void CHqlField::sethash()
  5352. {
  5353. CHqlExpression::sethash();
  5354. HASHFIELD(id);
  5355. }
  5356. //==============================================================================================================
  5357. CHqlRow::CHqlRow(node_operator op, ITypeInfo * type, HqlExprArray & _ownedOperands)
  5358. : CHqlExpressionWithType(op, type, _ownedOperands)
  5359. {
  5360. switch (op)
  5361. {
  5362. case no_select:
  5363. if (!hasAttribute(newAtom))
  5364. {
  5365. normalized.setown(calcNormalizedSelector());
  5366. }
  5367. break;
  5368. }
  5369. switch (op)
  5370. {
  5371. case no_activetable:
  5372. case no_self:
  5373. case no_left:
  5374. case no_right:
  5375. case no_activerow:
  5376. case no_top:
  5377. break;
  5378. default:
  5379. infoFlags |= HEFcontainsDataset;
  5380. break;
  5381. }
  5382. }
  5383. CHqlRow *CHqlRow::makeRow(node_operator op, ITypeInfo * type, HqlExprArray & args)
  5384. {
  5385. CHqlRow *e = new CHqlRow(op, type, args);
  5386. return (CHqlRow *) e->closeExpr();
  5387. }
  5388. IHqlExpression * CHqlRow::clone(HqlExprArray &newkids)
  5389. {
  5390. return createRow(op, newkids);
  5391. }
  5392. IAtom * CHqlRow::queryName() const
  5393. {
  5394. switch (op)
  5395. {
  5396. case no_left: return leftAtom;
  5397. case no_right: return rightAtom;
  5398. case no_self: return selfAtom;
  5399. case no_activetable: return activeAtom;
  5400. case no_top: return topAtom;
  5401. }
  5402. return NULL;
  5403. }
  5404. IHqlExpression *CHqlRow::queryNormalizedSelector(bool skipIndex)
  5405. {
  5406. if (!skipIndex || (op != no_selectnth))
  5407. return normalized.get() ? normalized.get() : this;
  5408. return queryChild(0)->queryNormalizedSelector(skipIndex);
  5409. }
  5410. IHqlSimpleScope *CHqlRow::querySimpleScope()
  5411. {
  5412. return QUERYINTERFACE(queryUnqualifiedType(type->queryChildType()), IHqlSimpleScope);
  5413. }
  5414. IHqlDataset *CHqlRow::queryDataset()
  5415. {
  5416. IHqlExpression * dataset = queryChild(0);
  5417. return dataset ? dataset->queryDataset() : NULL;
  5418. }
  5419. //==============================================================================================================
  5420. static bool isMany(IHqlExpression * expr)
  5421. {
  5422. switch (expr->getOperator())
  5423. {
  5424. case no_attr:
  5425. case no_attr_expr:
  5426. case no_attr_link:
  5427. return (expr->queryName() == manyAtom);
  5428. case no_range:
  5429. return isMany(expr->queryChild(1));
  5430. case no_constant:
  5431. return (expr->queryValue()->getIntValue() > 1);
  5432. default:
  5433. UNIMPLEMENTED;
  5434. }
  5435. }
  5436. // Is this numeric expression evaluated to zero?
  5437. bool isZero(IHqlExpression * expr)
  5438. {
  5439. IValue * value = expr->queryValue();
  5440. if (value)
  5441. {
  5442. switch (value->queryType()->getTypeCode())
  5443. {
  5444. case type_real:
  5445. return (value->getRealValue() == 0);
  5446. case type_boolean:
  5447. case type_int:
  5448. case type_date:
  5449. case type_bitfield:
  5450. case type_swapint:
  5451. case type_packedint:
  5452. return (value->getIntValue() == 0);
  5453. default:
  5454. {
  5455. Owned<IValue> zero = value->queryType()->castFrom(true, I64C(0));
  5456. return value->compare(zero) == 0;
  5457. }
  5458. }
  5459. }
  5460. if (expr->getOperator() == no_translated)
  5461. return isZero(expr->queryChild(0));
  5462. return false;
  5463. }
  5464. // Return -1 is constant is negative, 1 if positive, 0 if zero
  5465. static int compareConstantZero(IHqlExpression * expr)
  5466. {
  5467. assertex(expr->getOperator() == no_constant);
  5468. IValue * value = expr->queryValue();
  5469. // MORE: optimising this for int and real could save some cycles
  5470. Owned<IValue> zero = value->queryType()->castFrom(true, I64C(0));
  5471. return value->compare(zero);
  5472. }
  5473. // If it's at all possible (but not necessarily sure) that expr could be negative
  5474. // Default is true (maybe). Use isNegative for a clear answer
  5475. bool couldBeNegative(IHqlExpression * expr)
  5476. {
  5477. ITypeInfo * type = expr->queryType();
  5478. if (!isNumericType(type))
  5479. return false;
  5480. if (!type->isSigned())
  5481. return false;
  5482. if (isCast(expr) && castPreservesValueAndOrder(expr))
  5483. return couldBeNegative(expr->queryChild(0));
  5484. if (expr->getOperator() == no_constant)
  5485. return (compareConstantZero(expr) == -1);
  5486. // Default is a conservative maybe
  5487. return true;
  5488. }
  5489. // If expr is negative for sure.
  5490. // Default is false (not sure). Use couldBeNegative for possibilities
  5491. bool isNegative(IHqlExpression * expr)
  5492. {
  5493. if (expr->getOperator() == no_constant)
  5494. return (compareConstantZero(expr) == -1);
  5495. if (!couldBeNegative(expr))
  5496. return false;
  5497. if (expr->getOperator() == no_translated)
  5498. return isNegative(expr->queryChild(0));
  5499. // When unsure, say no
  5500. return false;
  5501. }
  5502. bool isChildRelationOf(IHqlExpression * child, IHqlExpression * other)
  5503. {
  5504. if (!other)
  5505. return false;
  5506. if (child->getOperator() != no_select)
  5507. {
  5508. IHqlDataset * otherDs = other->queryDataset();
  5509. if (!otherDs) return false;
  5510. other = queryExpression(otherDs->queryRootTable());
  5511. IHqlDataset * childDs = child->queryDataset();
  5512. if (!childDs) return false;
  5513. child = queryExpression(childDs->queryRootTable());
  5514. if (!other || !child)
  5515. return false;
  5516. }
  5517. IHqlDataset * searchDs = child->queryDataset();;
  5518. if (!searchDs)
  5519. return false;
  5520. IHqlExpression * search = searchDs->queryContainer();
  5521. while (search)
  5522. {
  5523. if (search == other)
  5524. return true;
  5525. IHqlDataset * searchDs = search->queryDataset();
  5526. if (!searchDs)
  5527. return false;
  5528. search = searchDs->queryContainer();
  5529. }
  5530. return false;
  5531. }
  5532. bool isInImplictScope(IHqlExpression * scope, IHqlExpression * dataset)
  5533. {
  5534. if (!scope)
  5535. return false;
  5536. IHqlDataset * scopeDs = scope->queryDataset();
  5537. IHqlDataset * datasetDs = dataset->queryDataset();
  5538. if (!scopeDs || !datasetDs)
  5539. return false;
  5540. if (isChildRelationOf(scope, dataset))
  5541. return true;
  5542. return false;
  5543. }
  5544. //===========================================================================
  5545. CHqlDictionary *CHqlDictionary::makeDictionary(node_operator _op, ITypeInfo *type, HqlExprArray &_ownedOperands)
  5546. {
  5547. CHqlDictionary *e = new CHqlDictionary(_op, type, _ownedOperands);
  5548. return (CHqlDictionary *) e->closeExpr();
  5549. }
  5550. CHqlDictionary::CHqlDictionary(node_operator _op, ITypeInfo *_type, HqlExprArray &_ownedOperands)
  5551. : CHqlExpressionWithType(_op, _type, _ownedOperands)
  5552. {
  5553. if (op == no_select)
  5554. normalized.setown(calcNormalizedSelector());
  5555. }
  5556. CHqlDictionary::~CHqlDictionary()
  5557. {
  5558. }
  5559. IHqlExpression *CHqlDictionary::clone(HqlExprArray &newkids)
  5560. {
  5561. return createDictionary(op, newkids);
  5562. }
  5563. IHqlExpression * CHqlDictionary::queryNormalizedSelector(bool skipIndex)
  5564. {
  5565. if (!normalized)
  5566. return this;
  5567. if (!skipIndex)
  5568. return normalized;
  5569. return normalized->queryNormalizedSelector(skipIndex);
  5570. }
  5571. //===========================================================================
  5572. CHqlDataset *CHqlDataset::makeDataset(node_operator _op, ITypeInfo *type, HqlExprArray &_ownedOperands)
  5573. {
  5574. CHqlDataset *e = new CHqlDataset(_op, type, _ownedOperands);
  5575. return (CHqlDataset *) e->closeExpr();
  5576. }
  5577. IHqlSimpleScope *CHqlDataset::querySimpleScope()
  5578. {
  5579. return QUERYINTERFACE(queryUnqualifiedType(queryRecordType()), IHqlSimpleScope);
  5580. }
  5581. IHqlExpression *CHqlDataset::clone(HqlExprArray &newkids)
  5582. {
  5583. return createDataset(op, newkids);
  5584. }
  5585. IHqlDataset *CHqlDataset::queryTable()
  5586. {
  5587. if (op == no_compound)
  5588. return queryChild(1)->queryDataset()->queryTable();
  5589. if (definesColumnList(this))
  5590. return this;
  5591. IHqlExpression* child = queryChild(0);
  5592. assert(child);
  5593. IHqlDataset* dataset = child->queryDataset();
  5594. if (dataset)
  5595. return dataset->queryTable();
  5596. StringBuffer s("queryDataset() return NULL for: ");
  5597. s.append(getOpString(op));
  5598. throw MakeStringExceptionDirect(2, s.str());
  5599. }
  5600. void CHqlDataset::sethash()
  5601. {
  5602. CHqlExpression::sethash();
  5603. }
  5604. //==============================================================================================================
  5605. CHqlDataset::CHqlDataset(node_operator _op, ITypeInfo *_type, HqlExprArray &_ownedOperands)
  5606. : CHqlExpressionWithType(_op, _type, _ownedOperands)
  5607. {
  5608. infoFlags &= ~(HEFfunctionOfGroupAggregate|HEFassertkeyed); // parent dataset should never have keyed attribute
  5609. infoFlags &= ~(HEF2assertstepped);
  5610. infoFlags |= HEFcontainsDataset;
  5611. cacheParent();
  5612. //MORE we may want some datasets (e.g., null, temptable?) to be table invariant, but it may
  5613. //cause problems with datasets that are created on the fly.
  5614. }
  5615. CHqlDataset::~CHqlDataset()
  5616. {
  5617. ::Release(container);
  5618. }
  5619. bool CHqlDataset::equals(const IHqlExpression & r) const
  5620. {
  5621. if (CHqlExpression::equals(r))
  5622. {
  5623. const CHqlDataset & other = (const CHqlDataset &)r;
  5624. //No need to check name - since it is purely derived from one of the arguments
  5625. return true;
  5626. }
  5627. return false;
  5628. }
  5629. /* If a dataset is derived from a base dataset ds, and satisfying:
  5630. 1) It does not change the structure of ds
  5631. 2) It does not change any field value of a record (e.g. anything that is related to a transform)
  5632. Then ds is the parent dataset of the derived dataset.
  5633. Note that the derived dataset can:
  5634. 1) has fewer records than ds (by filter, selection, sampling etc)
  5635. 2) has different order for records (by sorting)
  5636. 3) has fewer fields (by selecting fields, like TABLE)
  5637. */
  5638. void CHqlDataset::cacheParent()
  5639. {
  5640. container = NULL;
  5641. rootTable = NULL;
  5642. switch (op)
  5643. {
  5644. case no_aggregate:
  5645. case no_newaggregate:
  5646. case no_newusertable:
  5647. if (isAggregateDataset(this))
  5648. {
  5649. rootTable = queryChild(0)->queryDataset()->queryRootTable();
  5650. break;
  5651. }
  5652. //Fallthrough...
  5653. case no_selectfields:
  5654. case no_keyed:
  5655. // change ordering
  5656. case no_sort:
  5657. case no_subsort:
  5658. case no_sorted:
  5659. case no_stepped:
  5660. case no_cosort:
  5661. case no_preload:
  5662. case no_assertsorted:
  5663. case no_assertgrouped:
  5664. case no_assertdistributed:
  5665. // grouping: can only select fields in groupby - which is checked in checkGrouping()
  5666. case no_group:
  5667. case no_cogroup:
  5668. case no_grouped:
  5669. // distributing:
  5670. case no_distribute:
  5671. case no_distributed:
  5672. case no_preservemeta:
  5673. // fewer records
  5674. case no_filter:
  5675. case no_choosen:
  5676. case no_choosesets:
  5677. case no_selectnth:
  5678. case no_dedup:
  5679. case no_enth:
  5680. case no_sample:
  5681. case no_limit:
  5682. case no_catchds:
  5683. // case no_keyedlimit:
  5684. case no_topn:
  5685. case no_keyeddistribute:
  5686. {
  5687. IHqlExpression * inDs = queryChild(0);
  5688. IHqlDataset* ds = inDs->queryDataset();
  5689. if (ds)
  5690. {
  5691. IHqlDataset * parent = ds->queryTable();
  5692. rootTable = parent->queryRootTable();
  5693. }
  5694. else
  5695. {
  5696. PrintLog("cacheParent->queryDataset get NULL for: %s", getOpString(inDs->getOperator()));
  5697. }
  5698. }
  5699. break;
  5700. case no_keyindex:
  5701. case no_newkeyindex:
  5702. case no_temptable:
  5703. case no_inlinetable:
  5704. case no_xmlproject:
  5705. case no_datasetfromrow:
  5706. case no_datasetfromdictionary:
  5707. case no_fail:
  5708. case no_skip:
  5709. case no_field:
  5710. case no_httpcall:
  5711. case no_soapcall:
  5712. case no_newsoapcall:
  5713. case no_workunit_dataset:
  5714. case no_getgraphresult:
  5715. case no_getgraphloopresult:
  5716. case no_getresult:
  5717. case no_null:
  5718. case no_anon:
  5719. case no_pseudods:
  5720. case no_activetable:
  5721. case no_alias:
  5722. case no_id2blob:
  5723. case no_externalcall:
  5724. case no_call:
  5725. case no_rows:
  5726. case no_rowsetindex:
  5727. case no_rowsetrange:
  5728. case no_internalselect:
  5729. case no_delayedselect:
  5730. case no_libraryselect:
  5731. case no_purevirtual:
  5732. case no_unboundselect:
  5733. case no_libraryscopeinstance:
  5734. case no_libraryinput:
  5735. rootTable = this;
  5736. break;
  5737. case no_mergejoin:
  5738. case no_nwayjoin:
  5739. case no_nwaymerge:
  5740. rootTable = this; //?
  5741. break;
  5742. case no_table:
  5743. {
  5744. rootTable = this;
  5745. IHqlExpression * parentArg = queryChild(3);
  5746. if (parentArg)
  5747. {
  5748. IHqlDataset * pDataset = parentArg->queryDataset();
  5749. if (pDataset)
  5750. {
  5751. IHqlDataset * parent = pDataset->queryTable();
  5752. if (parent)
  5753. {
  5754. container = ::queryExpression(parent->queryRootTable());
  5755. container->Link();
  5756. }
  5757. }
  5758. }
  5759. }
  5760. break;
  5761. case no_combine:
  5762. case no_combinegroup:
  5763. case no_join: // default join to following the left hand side.
  5764. case no_comma:
  5765. case no_process:
  5766. case no_related:
  5767. rootTable = queryChild(0)->queryDataset()->queryRootTable();
  5768. break;
  5769. case no_compound:
  5770. case no_fetch:
  5771. rootTable = queryChild(1)->queryDataset()->queryRootTable();
  5772. break;
  5773. case no_select:
  5774. {
  5775. rootTable = this;
  5776. normalized.setown(calcNormalizedSelector());
  5777. IHqlExpression * ds = queryChild(0);
  5778. container = LINK(queryDatasetCursor(ds)->queryNormalizedSelector(false));
  5779. #ifdef _DEBUG
  5780. assertex(!hasAttribute(newAtom) || !isAlwaysActiveRow(ds));
  5781. #endif
  5782. break;
  5783. }
  5784. case no_if:
  5785. {
  5786. IHqlDataset * rootLeft = queryChild(1)->queryDataset()->queryRootTable();
  5787. IHqlExpression * right = queryRealChild(this, 2);
  5788. if (right)
  5789. {
  5790. IHqlDataset * rootRight = right->queryDataset()->queryRootTable();
  5791. if (rootLeft == rootRight)
  5792. rootTable = rootLeft;
  5793. }
  5794. break;
  5795. }
  5796. case no_addfiles:
  5797. case no_chooseds:
  5798. default:
  5799. if (getNumChildTables(this) == 1)
  5800. {
  5801. IHqlDataset * childDataset = queryChild(0)->queryDataset();
  5802. assertex(childDataset);
  5803. rootTable = childDataset->queryRootTable();
  5804. }
  5805. break;
  5806. }
  5807. if (op != no_select)
  5808. {
  5809. IHqlDataset * table = queryTable();
  5810. IHqlExpression * tableExpr = ::queryExpression(table);
  5811. if (tableExpr != this)
  5812. {
  5813. normalized.set(tableExpr->queryNormalizedSelector());
  5814. }
  5815. }
  5816. }
  5817. bool CHqlDataset::isAggregate()
  5818. {
  5819. return isAggregateDataset(this);
  5820. }
  5821. IHqlExpression * CHqlDataset::queryNormalizedSelector(bool skipIndex)
  5822. {
  5823. if (!normalized)
  5824. return this;
  5825. if (!skipIndex)
  5826. return normalized;
  5827. return normalized->queryNormalizedSelector(skipIndex);
  5828. }
  5829. IHqlExpression * queryRoot(IHqlExpression * expr)
  5830. {
  5831. while ((expr->getOperator() == no_select) && expr->isDatarow())
  5832. expr = expr->queryChild(0);
  5833. IHqlDataset * dataset = expr->queryDataset();
  5834. if (!dataset)
  5835. return NULL;
  5836. return queryExpression(dataset->queryRootTable());
  5837. }
  5838. IHqlExpression * queryTable(IHqlExpression * dataset)
  5839. {
  5840. IHqlDataset * ds = dataset->queryDataset();
  5841. if (!ds)
  5842. return NULL;
  5843. return queryExpression(ds->queryTable());
  5844. }
  5845. node_operator queryTableMode(IHqlExpression * expr)
  5846. {
  5847. if (!expr)
  5848. return no_none;
  5849. switch (expr->getOperator())
  5850. {
  5851. case no_table:
  5852. {
  5853. node_operator modeOp = expr->queryChild(2)->getOperator();
  5854. if (modeOp == no_thor)
  5855. return no_flat;
  5856. return modeOp;
  5857. }
  5858. }
  5859. return no_none;
  5860. }
  5861. //==============================================================================================================
  5862. CHqlRecord::CHqlRecord() : CHqlExpressionWithTables(no_record)
  5863. {
  5864. thisAlignment = 0;
  5865. }
  5866. CHqlRecord::CHqlRecord(HqlExprArray &operands) : CHqlExpressionWithTables(no_record)
  5867. {
  5868. setOperands(operands);
  5869. thisAlignment = 0;
  5870. insertSymbols(this);
  5871. }
  5872. bool CHqlRecord::equals(const IHqlExpression & r) const
  5873. {
  5874. if (CHqlExpression::equals(r))
  5875. {
  5876. return true;
  5877. }
  5878. return false;
  5879. }
  5880. unsigned CHqlRecord::getAlignment()
  5881. {
  5882. if (!thisAlignment)
  5883. {
  5884. unsigned numFields = numChildren();
  5885. for (unsigned i = 0; i < numFields; i++)
  5886. {
  5887. IHqlExpression *field = queryChild(i);
  5888. ITypeInfo * type = field->queryType();
  5889. if (type)
  5890. {
  5891. size32_t align = type->getAlignment();
  5892. if (align > thisAlignment)
  5893. thisAlignment = align;
  5894. }
  5895. }
  5896. }
  5897. return thisAlignment;
  5898. }
  5899. IHqlExpression *CHqlRecord::addOperand(IHqlExpression *field)
  5900. {
  5901. CHqlExpression::addOperand(field);
  5902. insertSymbols(field);
  5903. return this;
  5904. }
  5905. void CHqlRecord::sethash()
  5906. {
  5907. // Can't use base class as that includes type (== this) which would make it different every time
  5908. setInitialHash(0);
  5909. assertex(fields.count() != 0 || isEmptyRecord(this));
  5910. }
  5911. IHqlExpression * CHqlRecord::clone(HqlExprArray &newkids)
  5912. {
  5913. CHqlRecord* e = new CHqlRecord(newkids);
  5914. return e->closeExpr();
  5915. }
  5916. unsigned CHqlRecord::getCrc()
  5917. {
  5918. return getExpressionCRC(this);
  5919. }
  5920. void CHqlRecord::insertSymbols(IHqlExpression * expr)
  5921. {
  5922. switch (expr->getOperator())
  5923. {
  5924. case no_field:
  5925. {
  5926. IAtom * name = expr->queryName();
  5927. if (name)
  5928. fields.setValue(name, expr);
  5929. }
  5930. break;
  5931. case no_ifblock:
  5932. expr = expr->queryChild(1);
  5933. //fall through:
  5934. case no_record:
  5935. {
  5936. ForEachChild(idx, expr)
  5937. insertSymbols(expr->queryChild(idx));
  5938. }
  5939. break;
  5940. case no_attr:
  5941. case no_attr_expr:
  5942. case no_attr_link:
  5943. break;
  5944. default:
  5945. assertex("Unknown expression type added to record");
  5946. break;
  5947. }
  5948. }
  5949. ITypeInfo * CHqlRecord::queryType() const
  5950. {
  5951. return const_cast<CHqlRecord *>(this);
  5952. }
  5953. ITypeInfo * CHqlRecord::getType()
  5954. {
  5955. CHqlRecord::Link();
  5956. return this;
  5957. }
  5958. CHqlRecord::~CHqlRecord()
  5959. {
  5960. }
  5961. /* return: linked */
  5962. IHqlExpression *CHqlRecord::lookupSymbol(IIdAtom * fieldName)
  5963. {
  5964. IHqlExpression *ret = fields.getValue(fieldName->lower());
  5965. ::Link(ret);
  5966. return ret;
  5967. }
  5968. /* does not affect linkage */
  5969. bool CHqlRecord::assignableFrom(ITypeInfo * source)
  5970. {
  5971. switch(source->getTypeCode())
  5972. {
  5973. case type_groupedtable:
  5974. case type_dictionary:
  5975. case type_table:
  5976. case type_row:
  5977. case type_transform:
  5978. return assignableFrom(source->queryChildType());
  5979. case type_record:
  5980. {
  5981. if (numChildren() == 0 || recordTypesMatch(source, this))
  5982. return true;
  5983. //Record inheritance. If the first entry in the source record is also a record, then check if compatible.
  5984. IHqlExpression * other = ::queryRecord(source);
  5985. ForEachChild(i, other)
  5986. {
  5987. IHqlExpression * cur = other->queryChild(i);
  5988. switch (cur->getOperator())
  5989. {
  5990. case no_ifblock:
  5991. case no_field:
  5992. return false;
  5993. case no_record:
  5994. return assignableFrom(cur->queryType());
  5995. }
  5996. }
  5997. return false;
  5998. }
  5999. default:
  6000. return false;
  6001. }
  6002. }
  6003. StringBuffer &CHqlRecord::getECLType(StringBuffer & out)
  6004. {
  6005. return out.append(queryTypeName());
  6006. }
  6007. //==============================================================================================================
  6008. CHqlAnnotation::CHqlAnnotation(IHqlExpression * _body)
  6009. : CHqlExpression(_body ? _body->getOperator() : no_nobody)
  6010. {
  6011. body = _body;
  6012. if (!body)
  6013. body = LINK(cachedNoBody);
  6014. }
  6015. CHqlAnnotation::~CHqlAnnotation()
  6016. {
  6017. ::Release(body);
  6018. }
  6019. void CHqlAnnotation::sethash()
  6020. {
  6021. hashcode = 0;
  6022. HASHFIELD(body);
  6023. }
  6024. bool CHqlAnnotation::equals(const IHqlExpression & other) const
  6025. {
  6026. if (!isAlive()) return false;
  6027. if (getAnnotationKind() != other.getAnnotationKind())
  6028. return false;
  6029. const CHqlAnnotation * cast = static_cast<const CHqlAnnotation *>(&other);
  6030. if ((body != cast->body))
  6031. return false;
  6032. return true;
  6033. }
  6034. unsigned CHqlAnnotation::getInfoFlags() const
  6035. {
  6036. return body->getInfoFlags();
  6037. }
  6038. unsigned CHqlAnnotation::getInfoFlags2() const
  6039. {
  6040. return body->getInfoFlags2();
  6041. }
  6042. unsigned CHqlAnnotation::getSymbolFlags() const
  6043. {
  6044. return body->getSymbolFlags();
  6045. }
  6046. bool CHqlAnnotation::isConstant()
  6047. {
  6048. return body->isConstant();
  6049. }
  6050. bool CHqlAnnotation::isPure()
  6051. {
  6052. return body->isPure();
  6053. }
  6054. bool CHqlAnnotation::isAttribute() const
  6055. {
  6056. return body->isAttribute();
  6057. }
  6058. StringBuffer &CHqlAnnotation::toString(StringBuffer &s)
  6059. {
  6060. return body->toString(s);
  6061. }
  6062. IHqlExpression *CHqlAnnotation::clone(HqlExprArray &newkids)
  6063. {
  6064. OwnedHqlExpr newbody = body->clone(newkids);
  6065. return cloneAnnotation(newbody);
  6066. }
  6067. IHqlExpression * CHqlAnnotation::cloneAllAnnotations(IHqlExpression * newbody)
  6068. {
  6069. OwnedHqlExpr updatedBody = body->cloneAllAnnotations(newbody);
  6070. return cloneAnnotation(updatedBody);
  6071. }
  6072. bool CHqlAnnotation::isIndependentOfScope()
  6073. {
  6074. return body->isIndependentOfScope();
  6075. }
  6076. bool CHqlAnnotation::isIndependentOfScopeIgnoringInputs()
  6077. {
  6078. return body->isIndependentOfScopeIgnoringInputs();
  6079. }
  6080. bool CHqlAnnotation::usesSelector(IHqlExpression * selector)
  6081. {
  6082. return body->usesSelector(selector);
  6083. }
  6084. void CHqlAnnotation::gatherTablesUsed(CUsedTablesBuilder & used)
  6085. {
  6086. body->gatherTablesUsed(used);
  6087. }
  6088. void CHqlAnnotation::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope)
  6089. {
  6090. body->gatherTablesUsed(newScope, inScope);
  6091. }
  6092. IHqlExpression *CHqlAnnotation::queryChild(unsigned idx) const
  6093. {
  6094. return body->queryChild(idx);
  6095. }
  6096. IHqlExpression *CHqlAnnotation::queryAttribute(IAtom * propname) const
  6097. {
  6098. return body->queryAttribute(propname);
  6099. }
  6100. IHqlExpression * CHqlAnnotation::queryAnnotationParameter(unsigned idx) const
  6101. {
  6102. return CHqlExpression::queryChild(idx);
  6103. }
  6104. unsigned CHqlAnnotation::numChildren() const
  6105. {
  6106. return body->numChildren();
  6107. }
  6108. unsigned int CHqlAnnotation::getCachedEclCRC()
  6109. {
  6110. return body->getCachedEclCRC();
  6111. }
  6112. bool CHqlAnnotation::isExported() const
  6113. {
  6114. return body->isExported();
  6115. }
  6116. StringBuffer & CHqlAnnotation::getTextBuf(StringBuffer & out)
  6117. {
  6118. return body->getTextBuf(out);
  6119. }
  6120. IFileContents * CHqlAnnotation::queryDefinitionText() const
  6121. {
  6122. return body->queryDefinitionText();
  6123. }
  6124. IHqlExpression * CHqlAnnotation::addOperand(IHqlExpression * expr)
  6125. {
  6126. throwUnexpected();
  6127. return body->addOperand(expr);
  6128. }
  6129. bool CHqlAnnotation::isFullyBound() const
  6130. {
  6131. return body->isFullyBound();
  6132. }
  6133. IIdAtom * CHqlAnnotation::queryFullContainerId() const
  6134. {
  6135. return body->queryFullContainerId();
  6136. }
  6137. IHqlExpression * CHqlAnnotation::queryProperty(ExprPropKind kind)
  6138. {
  6139. return body->queryProperty(kind);
  6140. }
  6141. IHqlExpression * CHqlAnnotation::queryNormalizedSelector(bool skipIndex)
  6142. {
  6143. return body->queryNormalizedSelector(skipIndex);
  6144. }
  6145. IHqlExpression * CHqlAnnotation::queryExternalDefinition() const
  6146. {
  6147. return body->queryExternalDefinition();
  6148. }
  6149. IHqlExpression * CHqlAnnotation::queryFunctionDefinition() const
  6150. {
  6151. return body->queryFunctionDefinition();
  6152. }
  6153. IHqlSimpleScope * CHqlAnnotation::querySimpleScope()
  6154. {
  6155. return body->querySimpleScope();
  6156. }
  6157. IHqlScope * CHqlAnnotation::queryScope()
  6158. {
  6159. return body->queryScope();
  6160. }
  6161. IHqlDataset * CHqlAnnotation::queryDataset()
  6162. {
  6163. return body->queryDataset();
  6164. }
  6165. unsigned __int64 CHqlAnnotation::querySequenceExtra()
  6166. {
  6167. return body->querySequenceExtra();
  6168. }
  6169. IInterface * CHqlAnnotation::queryUnknownExtra()
  6170. {
  6171. return body->queryUnknownExtra();
  6172. }
  6173. IValue * CHqlAnnotation::queryValue() const
  6174. {
  6175. return body->queryValue();
  6176. }
  6177. IHqlExpression * CHqlAnnotation::queryBody(bool singleLevel)
  6178. {
  6179. //Not sure about the following...
  6180. if (body == cachedNoBody)
  6181. return NULL;
  6182. if (singleLevel)
  6183. return body;
  6184. return body->queryBody(singleLevel);
  6185. }
  6186. IPropertyTree * CHqlAnnotation::getDocumentation() const
  6187. {
  6188. return body->getDocumentation();
  6189. }
  6190. bool CHqlAnnotation::isGroupAggregateFunction()
  6191. {
  6192. return body->isGroupAggregateFunction();
  6193. }
  6194. bool CHqlAnnotation::isMacro()
  6195. {
  6196. return body->isMacro();
  6197. }
  6198. bool CHqlAnnotation::isType()
  6199. {
  6200. return body->isType();
  6201. }
  6202. bool CHqlAnnotation::isScope()
  6203. {
  6204. return body->isScope();
  6205. }
  6206. int CHqlAnnotation::getStartColumn() const
  6207. {
  6208. return body->getStartColumn();
  6209. }
  6210. int CHqlAnnotation::getStartLine() const
  6211. {
  6212. return body->getStartLine();
  6213. }
  6214. IAtom * CHqlAnnotation::queryName() const
  6215. {
  6216. return body->queryName();
  6217. }
  6218. IIdAtom * CHqlAnnotation::queryId() const
  6219. {
  6220. return body->queryId();
  6221. }
  6222. ITypeInfo * CHqlAnnotation::queryType() const
  6223. {
  6224. return body->queryType();
  6225. }
  6226. ITypeInfo * CHqlAnnotation::getType()
  6227. {
  6228. return body->getType();
  6229. }
  6230. //==============================================================================================================
  6231. CHqlCachedBoundFunction::CHqlCachedBoundFunction(IHqlExpression *func, bool _forceOutOfLineExpansion)
  6232. : CHqlExpressionWithTables(no_bound_func)
  6233. {
  6234. appendOperands(LINK(func), NULL);
  6235. if (_forceOutOfLineExpansion)
  6236. addOperand(createConstant(true));
  6237. }
  6238. ITypeInfo * CHqlCachedBoundFunction::queryType() const
  6239. {
  6240. return nullType;
  6241. }
  6242. ITypeInfo * CHqlCachedBoundFunction::getType()
  6243. {
  6244. return LINK(nullType);
  6245. }
  6246. IHqlExpression * CHqlCachedBoundFunction::clone(HqlExprArray &)
  6247. {
  6248. throwUnexpected();
  6249. return LINK(this);
  6250. }
  6251. #ifdef NEW_VIRTUAL_DATASETS
  6252. //Skeleton code to implement template functions using the standard binding mechanism (to behave more like c++ templates)
  6253. //However it would require moving lots of the semantic checking into the binding mechanism
  6254. //essentially parse to syntax tree, expand, semantically check. Needless to say it is likely to be a lot of work.
  6255. static void doGatherAbstractSelects(HqlExprArray & selects, IHqlExpression * expr, IHqlExpression * selector)
  6256. {
  6257. if (expr->queryTransformExtra())
  6258. return;
  6259. switch (expr->getOperator())
  6260. {
  6261. case no_attr:
  6262. return;
  6263. case no_select:
  6264. if (expr->queryChild(0)->queryNormalizedSelector() == selector)
  6265. {
  6266. if (selects.find(*expr) == NotFound)
  6267. selects.append(*LINK(expr));
  6268. return;
  6269. }
  6270. break;
  6271. }
  6272. ForEachChild(i, expr)
  6273. doGatherAbstractSelects(selects, expr->queryChild(i), selector);
  6274. expr->setTransformExtraUnlinked(expr);
  6275. }
  6276. static void gatherAbstractSelects(HqlExprArray & selects, IHqlExpression * expr, IHqlExpression * selector)
  6277. {
  6278. TransformMutexBlock procedure;
  6279. doGatherAbstractSelects(selects, expr, selector);
  6280. }
  6281. static void associateBindMap(HqlExprArray & selects, IHqlExpression * formal, IHqlExpression * actual, IHqlExpression * mapping)
  6282. {
  6283. IHqlSimpleScope * actualScope = actual->queryRecord()->querySimpleScope();
  6284. HqlExprArray maps;
  6285. mapping->unwindList(maps, no_comma);
  6286. unsigned numMaps = maps.ordinality();
  6287. for (unsigned i=0; i < numMaps; i+= 2)
  6288. {
  6289. IIdAtom * mapFrom = maps.item(i).queryName();
  6290. IIdAtom * mapTo = maps.item(i+1).queryName();
  6291. ForEachItemIn(j, selects)
  6292. {
  6293. IHqlExpression * selectFrom = &selects.item(j);
  6294. if (selectFrom->queryChild(1)->queryName() == mapFrom)
  6295. {
  6296. OwnedHqlExpr to = actualScope->lookupSymbol(mapTo);
  6297. if (!to)
  6298. throwError1(HQLERR_FieldInMapNotDataset, mapTo->str());
  6299. OwnedHqlExpr selectTo = createSelectExpr(LINK(actual), LINK(to));
  6300. if (selectFrom->queryTransformExtra())
  6301. throwError1(HQLERR_FieldAlreadyMapped, mapFrom->str());
  6302. selectFrom->setTransformExtraOwned(selectTo.getClear());
  6303. }
  6304. }
  6305. }
  6306. }
  6307. static void associateBindByName(HqlExprArray & selects, IHqlExpression * formal, IHqlExpression * actual)
  6308. {
  6309. IHqlSimpleScope * actualScope = actual->queryRecord()->querySimpleScope();
  6310. ForEachItemIn(i, selects)
  6311. {
  6312. IHqlExpression * selectFrom = &selects.item(i);
  6313. IHqlExpression * curFormal = selectFrom->queryChild(1);
  6314. if (!selectFrom->queryTransformExtra())
  6315. {
  6316. IIdAtom * name = curFormal->queryName();
  6317. OwnedHqlExpr to = actualScope->lookupSymbol(name);
  6318. if (!to)
  6319. {
  6320. if (isAbstractDataset(actual))
  6321. to.set(curFormal);
  6322. else
  6323. throwError1(HQLERR_FileNotInDataset, name->str());
  6324. }
  6325. OwnedHqlExpr selectTo = createSelectExpr(LINK(actual), LINK(to));
  6326. selectFrom->setTransformExtra(selectTo);
  6327. }
  6328. }
  6329. }
  6330. #endif
  6331. //---------------------------------------------------------------------------------------------------------------------
  6332. CHqlSymbolAnnotation::CHqlSymbolAnnotation(IIdAtom * _id, IIdAtom * _moduleId, IHqlExpression *_expr, IHqlExpression * _funcdef, unsigned _symbolFlags)
  6333. : CHqlAnnotation(_expr)
  6334. {
  6335. id = _id;
  6336. symbolFlags = _symbolFlags;
  6337. moduleId = _moduleId;
  6338. funcdef = _funcdef;
  6339. if (funcdef && containsInternalSelect(funcdef))
  6340. infoFlags |= HEFinternalSelect;
  6341. }
  6342. void CHqlSymbolAnnotation::sethash()
  6343. {
  6344. hashcode = 0;
  6345. HASHFIELD(id);
  6346. HASHFIELD(body);
  6347. HASHFIELD(moduleId);
  6348. }
  6349. CHqlSymbolAnnotation::~CHqlSymbolAnnotation()
  6350. {
  6351. ::Release(funcdef);
  6352. }
  6353. bool CHqlSymbolAnnotation::equals(const IHqlExpression & other) const
  6354. {
  6355. if (!CHqlAnnotation::equals(other))
  6356. return false;
  6357. //Must be a named symbol if got here
  6358. if (id != other.queryId())
  6359. return false;
  6360. if ((symbolFlags != other.getSymbolFlags()) || (funcdef != other.queryFunctionDefinition()))
  6361. return false;
  6362. if (moduleId != other.queryFullContainerId())
  6363. return false;
  6364. if (op == no_nobody)
  6365. {
  6366. //no_nobody is currently used for attributes that have had their text read
  6367. //but have not been parsed. If so, we need to check the text matches.
  6368. //There should almost certainly be a different representation for delayed expressions.
  6369. if (!isSameText(queryDefinitionText(), other.queryDefinitionText()))
  6370. return false;
  6371. }
  6372. return true;
  6373. }
  6374. unsigned CHqlSymbolAnnotation::getSymbolFlags() const
  6375. {
  6376. return symbolFlags;
  6377. }
  6378. IHqlExpression * CHqlSymbolAnnotation::cloneAnnotation(IHqlExpression * newbody)
  6379. {
  6380. if (body == newbody)
  6381. return LINK(this);
  6382. return cloneSymbol(id, newbody, funcdef, NULL);
  6383. }
  6384. IHqlExpression *CHqlSymbolAnnotation::queryFunctionDefinition() const
  6385. {
  6386. return funcdef;
  6387. }
  6388. IHqlExpression *CHqlSymbolAnnotation::queryExpression()
  6389. {
  6390. return this;
  6391. }
  6392. //---------------------------------------------------------------------------------------------------------------------
  6393. inline unsigned combineSymbolFlags(unsigned symbolFlags, bool exported, bool shared)
  6394. {
  6395. return symbolFlags | (exported ? ob_exported : 0) | (shared ? ob_shared : 0);
  6396. }
  6397. CHqlSimpleSymbol::CHqlSimpleSymbol(IIdAtom * _id, IIdAtom * _module, IHqlExpression *_expr, IHqlExpression * _funcdef, unsigned _symbolFlags)
  6398. : CHqlSymbolAnnotation(_id, _module, _expr, _funcdef, _symbolFlags)
  6399. {
  6400. }
  6401. IHqlExpression *CHqlSimpleSymbol::makeSymbol(IIdAtom * _id, IIdAtom * _module, IHqlExpression *_expr, IHqlExpression * _funcdef, unsigned _flags)
  6402. {
  6403. CHqlSimpleSymbol *e = new CHqlSimpleSymbol(_id, _module, _expr, _funcdef, _flags);
  6404. return e->closeExpr();
  6405. }
  6406. IHqlExpression * CHqlSimpleSymbol::cloneSymbol(IIdAtom * optid, IHqlExpression * optnewbody, IHqlExpression * optnewfuncdef, HqlExprArray * optargs)
  6407. {
  6408. assertex(!optargs || optargs->ordinality() == 0);
  6409. IIdAtom * newid = optid ? optid : id;
  6410. IHqlExpression * newbody = optnewbody ? optnewbody : body;
  6411. IHqlExpression * newfuncdef = optnewfuncdef ? optnewfuncdef : funcdef;
  6412. if (newid == id && newbody==body && newfuncdef==funcdef)
  6413. return LINK(this);
  6414. return makeSymbol(newid, moduleId, LINK(newbody), LINK(newfuncdef), symbolFlags);
  6415. }
  6416. //---------------------------------------------------------------------------------------------------------------------
  6417. CHqlNamedSymbol::CHqlNamedSymbol(IIdAtom * _id, IIdAtom * _module, IHqlExpression *_expr, bool _exported, bool _shared, unsigned _symbolFlags)
  6418. : CHqlSymbolAnnotation(_id, _module, _expr, NULL, combineSymbolFlags(_symbolFlags, _exported, _shared))
  6419. {
  6420. startpos = 0;
  6421. bodypos = 0;
  6422. endpos = 0;
  6423. startLine = 0;
  6424. startColumn = 0;
  6425. }
  6426. CHqlNamedSymbol::CHqlNamedSymbol(IIdAtom * _id, IIdAtom * _module, IHqlExpression *_expr, IHqlExpression *_funcdef, bool _exported, bool _shared, unsigned _symbolFlags, IFileContents *_text, int _startLine, int _startColumn, int _startpos, int _bodypos, int _endpos)
  6427. : CHqlSymbolAnnotation(_id, _module, _expr, _funcdef, combineSymbolFlags(_symbolFlags, _exported, _shared))
  6428. {
  6429. text.set(_text);
  6430. startpos = _startpos;
  6431. bodypos = _bodypos;
  6432. endpos = _endpos;
  6433. startLine = _startLine;
  6434. startColumn = _startColumn;
  6435. }
  6436. CHqlNamedSymbol *CHqlNamedSymbol::makeSymbol(IIdAtom * _id, IIdAtom * _module, IHqlExpression *_expr, bool _exported, bool _shared, unsigned _flags)
  6437. {
  6438. CHqlNamedSymbol *e = new CHqlNamedSymbol(_id, _module, _expr, _exported, _shared, _flags);
  6439. return (CHqlNamedSymbol *) e->closeExpr();
  6440. }
  6441. CHqlNamedSymbol *CHqlNamedSymbol::makeSymbol(IIdAtom * _id, IIdAtom * _module, IHqlExpression *_expr, IHqlExpression *_funcdef, bool _exported, bool _shared, unsigned _flags, IFileContents *_text, int _startLine, int _startColumn, int _startpos, int _bodypos, int _endpos)
  6442. {
  6443. CHqlNamedSymbol *e = new CHqlNamedSymbol(_id, _module, _expr, _funcdef, _exported, _shared, _flags, _text, _startLine, _startColumn, _startpos, _bodypos, _endpos);
  6444. return (CHqlNamedSymbol *) e->closeExpr();
  6445. }
  6446. IHqlExpression * CHqlNamedSymbol::cloneSymbol(IIdAtom * optid, IHqlExpression * optnewbody, IHqlExpression * optnewfuncdef, HqlExprArray * optargs)
  6447. {
  6448. IIdAtom * newid = optid ? optid : id;
  6449. IHqlExpression * newbody = optnewbody ? optnewbody : body;
  6450. IHqlExpression * newfuncdef = optnewfuncdef ? optnewfuncdef : funcdef;
  6451. HqlExprArray * newoperands = optargs ? optargs : &operands;
  6452. if (newid == id && newbody==body && newfuncdef==funcdef)
  6453. {
  6454. if (newoperands == &operands || arraysSame(*newoperands, operands))
  6455. return LINK(this);
  6456. }
  6457. CHqlNamedSymbol * e = new CHqlNamedSymbol(newid, moduleId, LINK(newbody), LINK(newfuncdef), isExported(), isShared(), symbolFlags, text, startLine, startColumn, startpos, bodypos, endpos);
  6458. //NB: do not all doAppendOpeand() because the parameters to a named symbol do not change it's attributes - e.g., whether pure.
  6459. e->operands.ensure(newoperands->ordinality());
  6460. ForEachItemIn(idx, *newoperands)
  6461. e->operands.append(OLINK(newoperands->item(idx)));
  6462. return e->closeExpr();
  6463. }
  6464. IFileContents * CHqlNamedSymbol::getBodyContents()
  6465. {
  6466. return createFileContentsSubset(text, bodypos, getEndPos()-bodypos);
  6467. }
  6468. IFileContents * CHqlNamedSymbol::queryDefinitionText() const
  6469. {
  6470. return text;
  6471. }
  6472. ISourcePath * CHqlNamedSymbol::querySourcePath() const
  6473. {
  6474. if (text)
  6475. return text->querySourcePath();
  6476. return CHqlAnnotation::querySourcePath();
  6477. }
  6478. IHqlNamedAnnotation * queryNameAnnotation(IHqlExpression * expr)
  6479. {
  6480. IHqlExpression * symbol = queryNamedSymbol(expr);
  6481. if (!symbol)
  6482. return NULL;
  6483. return static_cast<IHqlNamedAnnotation *>(symbol->queryAnnotation());
  6484. }
  6485. //---------------------------------------------------------------------------------------------------------------------
  6486. bool isExported(IHqlExpression * expr)
  6487. {
  6488. IHqlNamedAnnotation * symbol = queryNameAnnotation(expr);
  6489. return (symbol && symbol->isExported());
  6490. }
  6491. bool isShared(IHqlExpression * expr)
  6492. {
  6493. IHqlNamedAnnotation * symbol = queryNameAnnotation(expr);
  6494. return (symbol && symbol->isShared());
  6495. }
  6496. bool isPublicSymbol(IHqlExpression * expr)
  6497. {
  6498. IHqlNamedAnnotation * symbol = queryNameAnnotation(expr);
  6499. return (symbol && symbol->isPublic());
  6500. }
  6501. bool isImport(IHqlExpression * expr)
  6502. {
  6503. IHqlExpression * symbol = queryNamedSymbol(expr);
  6504. return symbol && ((symbol->getSymbolFlags() & ob_import) != 0);
  6505. }
  6506. IECLError * queryAnnotatedWarning(const IHqlExpression * expr)
  6507. {
  6508. assertex(expr->getAnnotationKind() == annotate_warning);
  6509. const CHqlWarningAnnotation * cast = static_cast<const CHqlWarningAnnotation *>(expr);
  6510. return cast->queryWarning();
  6511. }
  6512. //==============================================================================================================
  6513. CHqlAnnotationWithOperands::CHqlAnnotationWithOperands(IHqlExpression *_body, HqlExprArray & _args)
  6514. : CHqlAnnotation(_body)
  6515. {
  6516. operands.ensure(_args.ordinality());
  6517. ForEachItemIn(i, _args)
  6518. operands.append(OLINK(_args.item(i)));
  6519. }
  6520. void CHqlAnnotationWithOperands::sethash()
  6521. {
  6522. // CHqlExpression::sethash();
  6523. setInitialHash(getAnnotationKind()); // hash the operands, not the body's
  6524. HASHFIELD(body);
  6525. }
  6526. bool CHqlAnnotationWithOperands::equals(const IHqlExpression & other) const
  6527. {
  6528. if (!CHqlAnnotation::equals(other))
  6529. return false;
  6530. const CHqlAnnotationWithOperands * cast = static_cast<const CHqlAnnotationWithOperands *>(&other);
  6531. if (operands.ordinality() != cast->operands.ordinality())
  6532. return false;
  6533. ForEachItemIn(i, operands)
  6534. {
  6535. if (&operands.item(i) != &cast->operands.item(i))
  6536. return false;
  6537. }
  6538. return true;
  6539. }
  6540. //==============================================================================================================
  6541. CHqlMetaAnnotation::CHqlMetaAnnotation(IHqlExpression *_body, HqlExprArray & _args)
  6542. : CHqlAnnotationWithOperands(_body, _args)
  6543. {
  6544. }
  6545. IHqlExpression * CHqlMetaAnnotation::cloneAnnotation(IHqlExpression * newbody)
  6546. {
  6547. if (body == newbody)
  6548. return LINK(this);
  6549. return createMetaAnnotation(LINK(newbody), operands);
  6550. }
  6551. IHqlExpression * CHqlMetaAnnotation::createAnnotation(IHqlExpression * _ownedBody, HqlExprArray & _args)
  6552. {
  6553. return (new CHqlMetaAnnotation(_ownedBody, _args))->closeExpr();
  6554. }
  6555. IHqlExpression * createMetaAnnotation(IHqlExpression * _ownedBody, HqlExprArray & _args)
  6556. {
  6557. return CHqlMetaAnnotation::createAnnotation(_ownedBody, _args);
  6558. }
  6559. //==============================================================================================================
  6560. CHqlParseMetaAnnotation::CHqlParseMetaAnnotation(IHqlExpression *_body, HqlExprArray & _args)
  6561. : CHqlAnnotationWithOperands(_body, _args)
  6562. {
  6563. }
  6564. IHqlExpression * CHqlParseMetaAnnotation::cloneAnnotation(IHqlExpression * newbody)
  6565. {
  6566. if (body == newbody)
  6567. return LINK(this);
  6568. return createParseMetaAnnotation(LINK(newbody), operands);
  6569. }
  6570. IHqlExpression * CHqlParseMetaAnnotation::createAnnotation(IHqlExpression * _ownedBody, HqlExprArray & _args)
  6571. {
  6572. return (new CHqlParseMetaAnnotation(_ownedBody, _args))->closeExpr();
  6573. }
  6574. IHqlExpression * createParseMetaAnnotation(IHqlExpression * _ownedBody, HqlExprArray & _args)
  6575. {
  6576. return CHqlParseMetaAnnotation::createAnnotation(_ownedBody, _args);
  6577. }
  6578. //==============================================================================================================
  6579. CHqlLocationAnnotation::CHqlLocationAnnotation(IHqlExpression *_body, ISourcePath * _sourcePath, int _lineno, int _column)
  6580. : CHqlAnnotation(_body), sourcePath(_sourcePath)
  6581. {
  6582. lineno = _lineno;
  6583. column = _column;
  6584. }
  6585. void CHqlLocationAnnotation::sethash()
  6586. {
  6587. // CHqlExpression::sethash();
  6588. setInitialHash(annotate_location); // has the operands, not the body's
  6589. HASHFIELD(body);
  6590. HASHFIELD(sourcePath);
  6591. HASHFIELD(lineno);
  6592. HASHFIELD(column);
  6593. }
  6594. IHqlExpression * CHqlLocationAnnotation::cloneAnnotation(IHqlExpression * newbody)
  6595. {
  6596. if (body == newbody)
  6597. return LINK(this);
  6598. return createLocationAnnotation(LINK(newbody), sourcePath, lineno, column);
  6599. }
  6600. bool CHqlLocationAnnotation::equals(const IHqlExpression & other) const
  6601. {
  6602. if (!CHqlAnnotation::equals(other))
  6603. return false;
  6604. const CHqlLocationAnnotation * cast = static_cast<const CHqlLocationAnnotation *>(&other);
  6605. if ((sourcePath != cast->sourcePath) || (lineno != cast->lineno) || (column != cast->column))
  6606. return false;
  6607. return true;
  6608. }
  6609. IHqlExpression * CHqlLocationAnnotation::createLocationAnnotation(IHqlExpression * _ownedBody, ISourcePath * _sourcePath, int _lineno, int _column)
  6610. {
  6611. return (new CHqlLocationAnnotation(_ownedBody, _sourcePath, _lineno, _column))->closeExpr();
  6612. }
  6613. IHqlExpression * createLocationAnnotation(IHqlExpression * _ownedBody, const ECLlocation & _location)
  6614. {
  6615. return createLocationAnnotation(_ownedBody, _location.sourcePath, _location.lineno, _location.column);
  6616. }
  6617. IHqlExpression * createLocationAnnotation(IHqlExpression * ownedBody, ISourcePath * sourcePath, int lineno, int column)
  6618. {
  6619. #ifdef _DEBUG
  6620. assertex(lineno != 0xdddddddd && column != 0xdddddddd);
  6621. assertex(lineno != 0xcdcdcdcd && column != 0xcdcdcdcd);
  6622. assertex(lineno != 0xcccccccc && column != 0xcccccccc);
  6623. #endif
  6624. return CHqlLocationAnnotation::createLocationAnnotation(ownedBody, sourcePath, lineno, column);
  6625. }
  6626. extern HQL_API bool okToAddAnnotation(IHqlExpression * expr)
  6627. {
  6628. switch (expr->getOperator())
  6629. {
  6630. case no_field:
  6631. case no_select:
  6632. case no_param:
  6633. case no_self:
  6634. case no_selfref:
  6635. case no_ifblock:
  6636. return false;
  6637. }
  6638. ITypeInfo * type = expr->queryType();
  6639. if (!type)
  6640. return false;
  6641. return true;
  6642. }
  6643. extern HQL_API bool okToAddLocation(IHqlExpression * expr)
  6644. {
  6645. #if defined(ANNOTATE_EXPR_POSITION) || defined(ANNOTATE_DATASET_POSITION)
  6646. if (!okToAddAnnotation(expr))
  6647. return false;
  6648. #endif
  6649. #if defined(ANNOTATE_EXPR_POSITION)
  6650. return true;
  6651. #elif defined(ANNOTATE_DATASET_POSITION)
  6652. ITypeInfo * type = expr->queryType();
  6653. switch (type->getTypeCode())
  6654. {
  6655. case type_dictionary:
  6656. case type_table:
  6657. case type_groupedtable:
  6658. case type_void:
  6659. return true;
  6660. }
  6661. return false;
  6662. #else
  6663. return false;
  6664. #endif
  6665. }
  6666. //==============================================================================================================
  6667. CHqlAnnotationExtraBase::CHqlAnnotationExtraBase(IHqlExpression *_body, IInterface * _ownedExtra)
  6668. : CHqlAnnotation(_body), extra(_ownedExtra)
  6669. {
  6670. }
  6671. void CHqlAnnotationExtraBase::sethash()
  6672. {
  6673. // CHqlExpression::sethash();
  6674. setInitialHash(getAnnotationKind());
  6675. HASHFIELD(body);
  6676. HASHFIELD(extra);
  6677. }
  6678. bool CHqlAnnotationExtraBase::equals(const IHqlExpression & other) const
  6679. {
  6680. if (!CHqlAnnotation::equals(other))
  6681. return false;
  6682. const CHqlAnnotationExtraBase * cast = static_cast<const CHqlAnnotationExtraBase *>(&other);
  6683. if (extra != cast->extra)
  6684. return false;
  6685. return true;
  6686. }
  6687. //==============================================================================================================
  6688. //equals could use the following instead...
  6689. // if (!areMatchingPTrees(doc, cast->doc))
  6690. // return false;
  6691. CHqlWarningAnnotation::CHqlWarningAnnotation(IHqlExpression *_body, IECLError * _ownedWarning)
  6692. : CHqlAnnotationExtraBase(_body, _ownedWarning)
  6693. {
  6694. }
  6695. IHqlExpression * CHqlWarningAnnotation::cloneAnnotation(IHqlExpression * newbody)
  6696. {
  6697. if (body == newbody)
  6698. return LINK(this);
  6699. return createWarningAnnotation(LINK(newbody), LINK(queryWarning()));
  6700. }
  6701. IHqlExpression * CHqlWarningAnnotation::createWarningAnnotation(IHqlExpression * _ownedBody, IECLError * _ownedWarning)
  6702. {
  6703. return (new CHqlWarningAnnotation(_ownedBody, _ownedWarning))->closeExpr();
  6704. }
  6705. IHqlExpression * createWarningAnnotation(IHqlExpression * _ownedBody, IECLError * _ownedWarning)
  6706. {
  6707. return CHqlWarningAnnotation::createWarningAnnotation(_ownedBody, _ownedWarning);
  6708. }
  6709. //==============================================================================================================
  6710. CHqlJavadocAnnotation::CHqlJavadocAnnotation(IHqlExpression *_body, IPropertyTree * _ownedJavadoc)
  6711. : CHqlAnnotationExtraBase(_body, _ownedJavadoc)
  6712. {
  6713. }
  6714. IHqlExpression * CHqlJavadocAnnotation::cloneAnnotation(IHqlExpression * newbody)
  6715. {
  6716. if (body == newbody)
  6717. return LINK(this);
  6718. return createJavadocAnnotation(LINK(newbody), LINK(queryDocumentation()));
  6719. }
  6720. IHqlExpression * CHqlJavadocAnnotation::createJavadocAnnotation(IHqlExpression * _ownedBody, IPropertyTree * _ownedJavadoc)
  6721. {
  6722. return (new CHqlJavadocAnnotation(_ownedBody, _ownedJavadoc))->closeExpr();
  6723. }
  6724. IHqlExpression * createJavadocAnnotation(IHqlExpression * _ownedBody, IPropertyTree * _ownedJavadoc)
  6725. {
  6726. return CHqlJavadocAnnotation::createJavadocAnnotation(_ownedBody, _ownedJavadoc);
  6727. }
  6728. //==============================================================================================================
  6729. CFileContents::CFileContents(IFile * _file, ISourcePath * _sourcePath) : file(_file), sourcePath(_sourcePath)
  6730. {
  6731. delayedRead = false;
  6732. if (!preloadFromFile())
  6733. file.clear();
  6734. }
  6735. bool CFileContents::preloadFromFile()
  6736. {
  6737. const char * filename = file->queryFilename();
  6738. if (stdIoHandle(filename)<0)
  6739. {
  6740. delayedRead = true;
  6741. return true;
  6742. }
  6743. //Read std input now to prevent blocking or other weird effects.
  6744. Owned<IFileIO> io = file->openShared(IFOread, IFSHread);
  6745. if (!io)
  6746. throw MakeStringException(0, "Failed to open input '%s'", filename);
  6747. MemoryBuffer mb;
  6748. size32_t rd;
  6749. size32_t sizeRead = 0;
  6750. do {
  6751. rd = io->read(sizeRead, STDIO_BUFFSIZE, mb.reserve(STDIO_BUFFSIZE+1)); // +1 as will need
  6752. sizeRead += rd;
  6753. mb.setLength(sizeRead);
  6754. } while (rd);
  6755. ensureUtf8(mb);
  6756. setContentsOwn(mb);
  6757. return true;
  6758. }
  6759. void CFileContents::ensureUtf8(MemoryBuffer & contents)
  6760. {
  6761. //If looks like utf16 then convert it to utf8
  6762. const void * zero = memchr(contents.bufferBase(), 0, contents.length());
  6763. if (zero)
  6764. {
  6765. MemoryBuffer translated;
  6766. if (convertToUtf8(translated, contents.length(), contents.bufferBase()))
  6767. contents.swapWith(translated);
  6768. else
  6769. throw MakeStringException(1, "File %s doesn't appear to be UTF8", file->queryFilename());
  6770. }
  6771. }
  6772. void CFileContents::ensureLoaded()
  6773. {
  6774. if (!delayedRead)
  6775. return;
  6776. delayedRead = false;
  6777. Owned<IFileIO> io = file->openShared(IFOread, IFSHread);
  6778. if (!io)
  6779. throw MakeStringException(1, "File %s could not be opened", file->queryFilename());
  6780. offset_t size = io->size();
  6781. if (size == (offset_t)-1)
  6782. throw MakeStringException(1, "File %s could not be read", file->queryFilename());
  6783. size32_t sizeToRead = (size32_t)size;
  6784. if (sizeToRead != size)
  6785. throw MakeStringException(1, "File %s is larger than 4Gb", file->queryFilename());
  6786. MemoryBuffer buffer;
  6787. buffer.ensureCapacity(sizeToRead+1);
  6788. byte * contents = static_cast<byte *>(buffer.reserve(sizeToRead));
  6789. size32_t sizeRead = io->read(0, sizeToRead, contents);
  6790. ensureUtf8(buffer);
  6791. setContentsOwn(buffer);
  6792. if (sizeRead != sizeToRead)
  6793. throw MakeStringException(1, "File %s only read %u of %u bytes", file->queryFilename(), sizeRead, sizeToRead);
  6794. }
  6795. CFileContents::CFileContents(const char *query, ISourcePath * _sourcePath)
  6796. : sourcePath(_sourcePath)
  6797. {
  6798. if (query)
  6799. setContents(strlen(query), query);
  6800. delayedRead = false;
  6801. }
  6802. CFileContents::CFileContents(unsigned len, const char *query, ISourcePath * _sourcePath)
  6803. : sourcePath(_sourcePath)
  6804. {
  6805. setContents(len, query);
  6806. delayedRead = false;
  6807. }
  6808. void CFileContents::setContents(unsigned len, const char * query)
  6809. {
  6810. void * buffer = fileContents.allocate(len+1);
  6811. memcpy(buffer, query, len);
  6812. ((byte *)buffer)[len] = '\0';
  6813. }
  6814. void CFileContents::setContentsOwn(MemoryBuffer & buffer)
  6815. {
  6816. buffer.append((byte)0);
  6817. buffer.truncate();
  6818. size32_t len = buffer.length();
  6819. fileContents.setOwn(len, buffer.detach());
  6820. }
  6821. IFileContents * createFileContentsFromText(unsigned len, const char * text, ISourcePath * sourcePath)
  6822. {
  6823. return new CFileContents(len, text, sourcePath);
  6824. }
  6825. IFileContents * createFileContentsFromText(const char * text, ISourcePath * sourcePath)
  6826. {
  6827. //MORE: Treatment of nulls?
  6828. return new CFileContents(text, sourcePath);
  6829. }
  6830. IFileContents * createFileContentsFromFile(const char * filename, ISourcePath * sourcePath)
  6831. {
  6832. Owned<IFile> file = createIFile(filename);
  6833. return new CFileContents(file, sourcePath);
  6834. }
  6835. IFileContents * createFileContents(IFile * file, ISourcePath * sourcePath)
  6836. {
  6837. return new CFileContents(file, sourcePath);
  6838. }
  6839. class CFileContentsSubset : public CInterfaceOf<IFileContents>
  6840. {
  6841. public:
  6842. CFileContentsSubset(IFileContents * _contents, size32_t _offset, size32_t _len)
  6843. : contents(_contents), offset(_offset), len(_len)
  6844. {
  6845. }
  6846. virtual IFile * queryFile() { return contents->queryFile(); }
  6847. virtual ISourcePath * querySourcePath() { return contents->querySourcePath(); }
  6848. virtual const char *getText() { return contents->getText() + offset; }
  6849. virtual size32_t length() { return len; }
  6850. protected:
  6851. Linked<IFileContents> contents;
  6852. size32_t offset;
  6853. size32_t len;
  6854. };
  6855. extern HQL_API IFileContents * createFileContentsSubset(IFileContents * contents, size32_t offset, size32_t len)
  6856. {
  6857. if (!contents)
  6858. return NULL;
  6859. if ((offset == 0) && (len == contents->length()))
  6860. return LINK(contents);
  6861. return new CFileContentsSubset(contents, offset, len);
  6862. }
  6863. //==============================================================================================================
  6864. CHqlScope::CHqlScope(node_operator _op, IIdAtom * _id, const char * _fullName)
  6865. : CHqlExpressionWithType(_op, NULL), id(_id), fullName(_fullName)
  6866. {
  6867. containerId = NULL;
  6868. type = this;
  6869. initContainer();
  6870. }
  6871. CHqlScope::CHqlScope(IHqlScope* scope)
  6872. : CHqlExpressionWithType(no_scope, NULL)
  6873. {
  6874. id = scope->queryId();
  6875. containerId = NULL;
  6876. fullName.set(scope->queryFullName());
  6877. CHqlScope* s = QUERYINTERFACE(scope, CHqlScope);
  6878. if (s && s->text)
  6879. text.set(s->text);
  6880. type = this;
  6881. initContainer();
  6882. }
  6883. CHqlScope::CHqlScope(node_operator _op)
  6884. : CHqlExpressionWithType(_op, NULL)
  6885. {
  6886. id = NULL;
  6887. containerId = NULL;
  6888. type = this;
  6889. }
  6890. CHqlScope::~CHqlScope()
  6891. {
  6892. if (type == this)
  6893. type = NULL;
  6894. }
  6895. void CHqlScope::initContainer()
  6896. {
  6897. if (fullName)
  6898. {
  6899. const char * dot = strrchr(fullName, '.');
  6900. if (dot)
  6901. containerId = createIdAtom(fullName, dot-fullName);
  6902. }
  6903. }
  6904. bool CHqlScope::assignableFrom(ITypeInfo * source)
  6905. {
  6906. if (source == this)
  6907. return true;
  6908. if (!source)
  6909. return false;
  6910. IHqlScope * scope = ::queryScope(source);
  6911. if (scope)
  6912. {
  6913. if (queryConcreteScope() == scope)
  6914. return true;
  6915. return scope->hasBaseClass(this);
  6916. }
  6917. return false;
  6918. }
  6919. bool CHqlScope::hasBaseClass(IHqlExpression * searchBase)
  6920. {
  6921. if (this == searchBase)
  6922. return true;
  6923. ForEachChild(i, this)
  6924. {
  6925. IHqlExpression * cur = queryChild(i);
  6926. if (cur->queryScope() && cur->queryScope()->hasBaseClass(searchBase))
  6927. return true;
  6928. }
  6929. return false;
  6930. }
  6931. void CHqlScope::sethash()
  6932. {
  6933. switch (op)
  6934. {
  6935. case no_service:
  6936. return;
  6937. case no_scope:
  6938. case no_virtualscope:
  6939. case no_libraryscope:
  6940. case no_libraryscopeinstance:
  6941. case no_concretescope:
  6942. break;
  6943. case no_param:
  6944. case no_privatescope:
  6945. case no_forwardscope:
  6946. case no_mergedscope:
  6947. setInitialHash(0);
  6948. return;
  6949. default:
  6950. throwUnexpectedOp(op);
  6951. }
  6952. setInitialHash(0);
  6953. //MORE: Should symbols also be added as operands - would make more sense....
  6954. SymbolTableIterator iter(symbols);
  6955. HqlExprCopyArray sortedSymbols;
  6956. sortedSymbols.ensure(symbols.count());
  6957. for (iter.first(); iter.isValid(); iter.next())
  6958. {
  6959. IHqlExpression *cur = symbols.mapToValue(&iter.query());
  6960. sortedSymbols.append(*cur);
  6961. }
  6962. sortedSymbols.sort(compareSymbolsByName);
  6963. ForEachItemIn(i, sortedSymbols)
  6964. {
  6965. IHqlExpression *cur = &sortedSymbols.item(i);
  6966. HASHFIELD(cur);
  6967. }
  6968. }
  6969. bool CHqlScope::equals(const IHqlExpression &r) const
  6970. {
  6971. return (this == &r);
  6972. }
  6973. unsigned CHqlScope::getCrc()
  6974. {
  6975. return getExpressionCRC(this);
  6976. }
  6977. IHqlExpression *CHqlScope::clone(HqlExprArray &newkids)
  6978. {
  6979. HqlExprArray syms;
  6980. getSymbols(syms);
  6981. return clone(newkids, syms)->queryExpression();
  6982. }
  6983. IHqlExpression * createFunctionDefinition(IIdAtom * id, IHqlExpression * value, IHqlExpression * parameters, IHqlExpression * defaults, IHqlExpression * attrs)
  6984. {
  6985. HqlExprArray args;
  6986. args.append(*value);
  6987. args.append(*parameters);
  6988. if (defaults)
  6989. args.append(*defaults);
  6990. if (attrs)
  6991. attrs->unwindList(args, no_comma);
  6992. return createFunctionDefinition(id, args);
  6993. }
  6994. IHqlExpression * createFunctionDefinition(IIdAtom * id, HqlExprArray & args)
  6995. {
  6996. IHqlExpression * body = &args.item(0);
  6997. IHqlExpression * formals = &args.item(1);
  6998. IHqlExpression * defaults = args.isItem(2) ? &args.item(2) : NULL;
  6999. #if 1
  7000. //This is a bit of a waste of time, but need to improve assignableFrom for a function type to ignore the uids.
  7001. QuickExpressionReplacer defaultReplacer;
  7002. HqlExprArray normalized;
  7003. ForEachChild(i, formals)
  7004. {
  7005. IHqlExpression * formal = formals->queryChild(i);
  7006. HqlExprArray attrs;
  7007. unwindChildren(attrs, formal);
  7008. IHqlExpression * normal = createParameter(formal->queryId(), UnadornedParameterIndex, formal->getType(), attrs);
  7009. normalized.append(*normal);
  7010. defaultReplacer.setMapping(formal->queryBody(), normal);
  7011. }
  7012. OwnedHqlExpr newFormals = formals->clone(normalized);
  7013. OwnedHqlExpr newDefaults = defaults ? defaultReplacer.transform(defaults) : NULL;
  7014. ITypeInfo * type = makeFunctionType(body->getType(), newFormals.getClear(), newDefaults.getClear());
  7015. #else
  7016. ITypeInfo * type = makeFunctionType(body->getType(), LINK(formals), LINK(defaults));
  7017. #endif
  7018. return createNamedValue(no_funcdef, type, id, args);
  7019. }
  7020. void CHqlScope::defineSymbol(IIdAtom * _id, IIdAtom * moduleName, IHqlExpression *value,
  7021. bool exported, bool shared, unsigned symbolFlags,
  7022. IFileContents *fc, int lineno, int column,
  7023. int _startpos, int _bodypos, int _endpos)
  7024. {
  7025. if (!moduleName)
  7026. moduleName = id;
  7027. IHqlExpression * symbol = createSymbol(_id, moduleName, value, NULL, exported, shared, symbolFlags, fc, lineno, column, _startpos, _bodypos, _endpos);
  7028. defineSymbol(symbol);
  7029. }
  7030. void CHqlScope::defineSymbol(IIdAtom * _id, IIdAtom * moduleName, IHqlExpression *value, bool exported, bool shared, unsigned symbolFlags)
  7031. {
  7032. assertex(_id);
  7033. if (!moduleName) moduleName = id;
  7034. defineSymbol(createSymbol(_id, moduleName, value, exported, shared, symbolFlags));
  7035. }
  7036. void CHqlScope::defineSymbol(IHqlExpression * expr)
  7037. {
  7038. assertex(expr->queryName());
  7039. assertex(hasNamedSymbol(expr));
  7040. // assertex(expr->queryBody() != expr && expr->queryName());
  7041. symbols.setValue(expr->queryName(), expr);
  7042. infoFlags |= (expr->getInfoFlags() & HEFalwaysInherit);
  7043. infoFlags2 |= (expr->getInfoFlags2() & HEF2alwaysInherit);
  7044. expr->Release();
  7045. }
  7046. void CHqlScope::removeSymbol(IIdAtom * _id)
  7047. {
  7048. symbols.remove(_id->lower());
  7049. //in general infoFlags needs recalculating - although currently I think this can only occur when a constant has been added
  7050. }
  7051. IHqlExpression *CHqlScope::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  7052. {
  7053. OwnedHqlExpr ret = symbols.getLinkedValue(searchName->lower());
  7054. if (!ret)
  7055. return NULL;
  7056. if (!(ret->isExported() || (lookupFlags & LSFsharedOK)))
  7057. return NULL;
  7058. return ret.getClear();
  7059. }
  7060. int CHqlScope::getPropInt(IAtom * a, int def) const
  7061. {
  7062. return def;
  7063. }
  7064. bool CHqlScope::getProp(IAtom * a, StringBuffer &ret) const
  7065. {
  7066. return false;
  7067. }
  7068. void CHqlScope::getSymbols(HqlExprArray& exprs) const
  7069. {
  7070. SymbolTable & localSymbols = const_cast<SymbolTable &>(symbols);
  7071. SymbolTableIterator iter(localSymbols);
  7072. for (iter.first(); iter.isValid(); iter.next())
  7073. {
  7074. IHqlExpression *cur = localSymbols.mapToValue(&iter.query());
  7075. if (!cur)
  7076. {
  7077. IAtom * name = * static_cast<IAtom * const *>(iter.query().getKey());
  7078. throw MakeStringException(ERR_INTERNAL_NOEXPR, "INTERNAL: getSymbol %s has no associated expression", name ? name->str() : "");
  7079. }
  7080. cur->Link();
  7081. exprs.append(*cur);
  7082. }
  7083. }
  7084. IHqlScope * CHqlScope::cloneAndClose(HqlExprArray & children, HqlExprArray & symbols)
  7085. {
  7086. ForEachItemIn(i1, children)
  7087. addOperand(LINK(&children.item(i1)));
  7088. ForEachItemIn(i2, symbols)
  7089. defineSymbol(&OLINK(symbols.item(i2)));
  7090. return closeExpr()->queryScope();
  7091. }
  7092. void CHqlScope::throwRecursiveError(IIdAtom * searchName)
  7093. {
  7094. StringBuffer filename;
  7095. if (fullName)
  7096. filename.append(fullName).append('.');
  7097. filename.append(*searchName);
  7098. StringBuffer msg("Definition of ");
  7099. msg.append(*searchName).append(" contains a recursive dependency");
  7100. throw createECLError(ERR_RECURSIVE_DEPENDENCY, msg.toCharArray(), filename, 0, 0, 1);
  7101. }
  7102. inline bool namesMatch(const char * lName, const char * rName)
  7103. {
  7104. if (lName == rName)
  7105. return true;
  7106. if (!lName || !rName)
  7107. return false;
  7108. return strcmp(lName, rName) == 0;
  7109. }
  7110. static bool scopesEqual(const IHqlScope * l, const IHqlScope * r)
  7111. {
  7112. HqlExprArray symL, symR;
  7113. if (!l || !r)
  7114. return l==r;
  7115. if (l->queryName() != r->queryName())
  7116. return false;
  7117. if (!namesMatch(l->queryFullName(), r->queryFullName()))
  7118. return false;
  7119. l->getSymbols(symL);
  7120. r->getSymbols(symR);
  7121. if (symL.ordinality() != symR.ordinality())
  7122. return false;
  7123. ForEachItemIn(i, symL)
  7124. if (symR.find(symL.item(i)) == NotFound)
  7125. return false;
  7126. return true;
  7127. }
  7128. //==============================================================================================================
  7129. CHqlRemoteScope::CHqlRemoteScope(IIdAtom * _name, const char * _fullName, IEclRepositoryCallback * _repository, IProperties* _props, IFileContents * _text, bool _lazy, IEclSource * _eclSource)
  7130. : CHqlScope(no_remotescope, _name, _fullName), eclSource(_eclSource)
  7131. {
  7132. text.set(_text);
  7133. ownerRepository = _repository;
  7134. loadedAllSymbols = !_lazy;
  7135. props = LINK(_props);
  7136. // Could delay creating this - it would be more efficient
  7137. resolved.setown(createPrivateScope());
  7138. }
  7139. CHqlRemoteScope::~CHqlRemoteScope()
  7140. {
  7141. ::Release(props);
  7142. }
  7143. bool CHqlRemoteScope::isImplicit() const
  7144. {
  7145. unsigned flags=getPropInt(flagsAtom, 0);
  7146. return (flags & PLUGIN_IMPLICIT_MODULE) != 0;
  7147. }
  7148. bool CHqlRemoteScope::isPlugin() const
  7149. {
  7150. unsigned flags=getPropInt(flagsAtom, 0);
  7151. return (flags & PLUGIN_DLL_MODULE) != 0;
  7152. }
  7153. void CHqlRemoteScope::sethash()
  7154. {
  7155. throwUnexpected();
  7156. setInitialHash(0);
  7157. }
  7158. bool CHqlRemoteScope::equals(const IHqlExpression &r) const
  7159. {
  7160. return (this == &r);
  7161. }
  7162. void CHqlRemoteScope::defineSymbol(IHqlExpression * expr)
  7163. {
  7164. IHqlExpression * body = expr->queryBody();
  7165. if (!body || (body->getOperator() == no_nobody))
  7166. {
  7167. //Defining an attribute defined in an ecl file - save the text of a symbol for later parsing
  7168. CHqlScope::defineSymbol(expr);
  7169. return;
  7170. }
  7171. //Slightly ugly and could do with improving....
  7172. //1) If text is specified for the remote scope then the whole text (rather than an individual symbol)
  7173. //will be being parsed, so this definition also needs to be added to the symbols
  7174. bool addToSymbols = false;
  7175. if (text)
  7176. addToSymbols = true;
  7177. else
  7178. {
  7179. //remote scopes should possibly be held on a separate list, but that would require extra lookups in ::lookupSymbol
  7180. //If this expression is defining a remote scope then it (currently) needs to be added to the symbols as well.
  7181. //Don't add other symbols so we don't lose the original text (e.g., if syntax errors in dependent attributes)
  7182. if (dynamic_cast<IHqlRemoteScope *>(body) != NULL)
  7183. addToSymbols = true;
  7184. }
  7185. resolved->defineSymbol(expr);
  7186. if (addToSymbols)
  7187. CHqlScope::defineSymbol(LINK(expr));
  7188. }
  7189. void CHqlRemoteScope::ensureSymbolsDefined(HqlLookupContext & ctx)
  7190. {
  7191. preloadSymbols(ctx, true);
  7192. }
  7193. void CHqlRemoteScope::preloadSymbols(HqlLookupContext & ctx, bool forceAll)
  7194. {
  7195. CriticalBlock block(generalCS);
  7196. if (!loadedAllSymbols)
  7197. {
  7198. if (text)
  7199. {
  7200. doParseScopeText(ctx);
  7201. }
  7202. else
  7203. {
  7204. repositoryLoadModule(ctx, forceAll);
  7205. }
  7206. }
  7207. }
  7208. void CHqlRemoteScope::doParseScopeText(HqlLookupContext & ctx)
  7209. {
  7210. loadedAllSymbols = true;
  7211. bool loadImplicit = true;
  7212. parseModule(queryScope(), text, ctx, NULL, loadImplicit);
  7213. }
  7214. IHqlExpression *CHqlRemoteScope::clone(HqlExprArray &newkids)
  7215. {
  7216. assertex(false);
  7217. Link();
  7218. return this;
  7219. }
  7220. IHqlExpression *CHqlRemoteScope::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  7221. {
  7222. // PrintLog("lookupSymbol %s#%d", searchName->getAtomNamePtr(),version);
  7223. preloadSymbols(ctx, false);
  7224. OwnedHqlExpr resolvedSym = resolved->lookupSymbol(searchName, lookupFlags, ctx);
  7225. if (resolvedSym && resolvedSym->getOperator() == no_processing)
  7226. {
  7227. if (lookupFlags & LSFrequired)
  7228. throwRecursiveError(searchName);
  7229. return NULL;
  7230. }
  7231. if (!(lookupFlags & LSFignoreBase))
  7232. {
  7233. if (resolvedSym)
  7234. {
  7235. ctx.noteExternalLookup(this, resolvedSym);
  7236. return resolvedSym.getClear();
  7237. }
  7238. }
  7239. OwnedHqlExpr ret = CHqlScope::lookupSymbol(searchName, LSFsharedOK|lookupFlags, ctx);
  7240. if(!ret || !ret->hasText())
  7241. {
  7242. OwnedHqlExpr symbol = repositoryLoadSymbol(searchName);
  7243. if(!symbol)
  7244. return NULL;
  7245. assertex(symbol->isNamedSymbol());
  7246. if (symbol->getOperator() != no_nobody)
  7247. {
  7248. //A nested remote scope...
  7249. resolved->defineSymbol(LINK(symbol));
  7250. return symbol.getClear();
  7251. }
  7252. ret.setown(symbol.getClear());
  7253. }
  7254. if ((lookupFlags & LSFignoreBase))
  7255. return ret.getClear();
  7256. StringBuffer filename;
  7257. if (fullName)
  7258. filename.append(fullName).append('.');
  7259. filename.append(*searchName);
  7260. IFileContents * contents = ret->queryDefinitionText();
  7261. if (!contents || (contents->length() == 0))
  7262. {
  7263. StringBuffer msg("Definition for ");
  7264. msg.append(*searchName).append(" contains no text");
  7265. throw createECLError(ERR_EXPORT_OR_SHARE, msg.toCharArray(), filename, 0, 0, 1);
  7266. }
  7267. OwnedHqlExpr recursionGuard = createSymbol(searchName, LINK(processingMarker), ob_exported);
  7268. resolved->defineSymbol(LINK(recursionGuard));
  7269. unsigned prevErrors = ctx.numErrors();
  7270. parseAttribute(this, contents, ctx, searchName);
  7271. OwnedHqlExpr newSymbol = resolved->lookupSymbol(searchName, LSFsharedOK|lookupFlags, ctx);
  7272. if (ctx.numErrors() != prevErrors)
  7273. {
  7274. //If there was an error processing the attribute then return unknown.
  7275. //The caller will also spot the difference in the error count, so we won't get attributes
  7276. //incorrectly defined.
  7277. if (newSymbol)
  7278. resolved->removeSymbol(searchName);
  7279. return NULL;
  7280. }
  7281. if(!newSymbol || (newSymbol->getOperator() == no_processing))
  7282. {
  7283. if (newSymbol)
  7284. resolved->removeSymbol(searchName);
  7285. StringBuffer msg("Definition must contain EXPORT or SHARED value for ");
  7286. msg.append(*searchName);
  7287. throw createECLError(ERR_EXPORT_OR_SHARE, msg.toCharArray(), filename, 0, 0, 1);
  7288. }
  7289. //Preserve ob_sandbox etc. annotated on the original definition, but not on the parsed code.
  7290. unsigned repositoryFlags=ret->getSymbolFlags();
  7291. IHqlNamedAnnotation * symbol = queryNameAnnotation(newSymbol);
  7292. assertex(symbol);
  7293. symbol->setRepositoryFlags(repositoryFlags);
  7294. if (repositoryFlags&ob_sandbox)
  7295. {
  7296. if (ctx.errs)
  7297. ctx.errs->reportWarning(CategoryInformation,WRN_DEFINITION_SANDBOXED,"Definition is sandboxed",filename,0,0,0);
  7298. }
  7299. if (!(newSymbol->isExported() || (lookupFlags & LSFsharedOK)))
  7300. return NULL;
  7301. return newSymbol.getClear();
  7302. }
  7303. void CHqlRemoteScope::getSymbols(HqlExprArray& exprs) const
  7304. {
  7305. //ensureSymbolsDefined should have been called before this function. If not the symbols won't be present...
  7306. //ugly ugly hack for getting plugin symbols.
  7307. if (text && resolved)
  7308. resolved->getSymbols(exprs);
  7309. else
  7310. CHqlScope::getSymbols(exprs);
  7311. }
  7312. IFileContents * CHqlRemoteScope::queryDefinitionText() const
  7313. {
  7314. return text;
  7315. }
  7316. int CHqlRemoteScope::getPropInt(IAtom * a, int def) const
  7317. {
  7318. if (props)
  7319. return props->getPropInt(a->getAtomNamePtr(), def);
  7320. else
  7321. return def;
  7322. }
  7323. bool CHqlRemoteScope::getProp(IAtom * a, StringBuffer &ret) const
  7324. {
  7325. return (props != NULL && props->getProp(a->getAtomNamePtr(), ret));
  7326. }
  7327. void CHqlRemoteScope::setProp(IAtom * a, int val)
  7328. {
  7329. if (!props)
  7330. props = createProperties();
  7331. props->setProp(a->getAtomNamePtr(), val);
  7332. }
  7333. void CHqlRemoteScope::setProp(IAtom * a, const char * val)
  7334. {
  7335. if (!props)
  7336. props = createProperties();
  7337. props->setProp(a->getAtomNamePtr(), val);
  7338. }
  7339. void CHqlRemoteScope::repositoryLoadModule(HqlLookupContext & ctx, bool forceAll)
  7340. {
  7341. if (ownerRepository->loadModule(this, ctx.errs, forceAll))
  7342. {
  7343. assertex(!text);
  7344. loadedAllSymbols = true;
  7345. }
  7346. }
  7347. IHqlExpression * CHqlRemoteScope::repositoryLoadSymbol(IIdAtom * attrName)
  7348. {
  7349. if (loadedAllSymbols)
  7350. return NULL;
  7351. OwnedHqlExpr symbol = ownerRepository->loadSymbol(this, attrName);
  7352. if(!symbol || !symbol->hasText())
  7353. return NULL;
  7354. return symbol.getClear();
  7355. }
  7356. extern HQL_API void ensureSymbolsDefined(IHqlScope * scope, HqlLookupContext & ctx)
  7357. {
  7358. scope->ensureSymbolsDefined(ctx);
  7359. }
  7360. extern HQL_API void ensureSymbolsDefined(IHqlExpression * scopeExpr, HqlLookupContext & ctx)
  7361. {
  7362. IHqlScope * scope = scopeExpr->queryScope();
  7363. if (scope)
  7364. scope->ensureSymbolsDefined(ctx);
  7365. }
  7366. //==============================================================================================================
  7367. void exportSymbols(IPropertyTree* data, IHqlScope * scope, HqlLookupContext & ctx)
  7368. {
  7369. scope->ensureSymbolsDefined(ctx);
  7370. data->setProp("@name", scope->queryFullName());
  7371. unsigned access = scope->getPropInt(accessAtom, 3);
  7372. HqlExprArray allSymbols;
  7373. scope->getSymbols(allSymbols);
  7374. ForEachItemIn(i, allSymbols)
  7375. {
  7376. IHqlExpression *cur = &allSymbols.item(i);
  7377. if (cur && !isImport(cur) && (cur->getOperator() != no_remotescope))
  7378. {
  7379. IPropertyTree * attr=createPTree("Attribute", ipt_caseInsensitive);
  7380. attr->setProp("@name", *cur->queryName());
  7381. unsigned symbolFlags = cur->getSymbolFlags();
  7382. if (cur->isExported())
  7383. symbolFlags |= ob_exported;
  7384. if(access >= cs_read)
  7385. symbolFlags |= ob_showtext;
  7386. attr->setPropInt("@flags", symbolFlags);
  7387. attr->setPropInt("@version", (1<<18 | 1));
  7388. attr->setPropInt("@latestVersion", (1<<18 | 1));
  7389. attr->setPropInt("@access", access);
  7390. if(cur->hasText())
  7391. {
  7392. StringBuffer attrText;
  7393. cur->getTextBuf(attrText);
  7394. attrText.clip();
  7395. attr->setProp("Text",attrText.str());
  7396. }
  7397. data->addPropTree("Attribute",attr);
  7398. }
  7399. }
  7400. }
  7401. //==============================================================================================================
  7402. CHqlLocalScope::CHqlLocalScope(IHqlScope* scope)
  7403. : CHqlScope(scope)
  7404. {
  7405. }
  7406. CHqlLocalScope::CHqlLocalScope(node_operator _op, IIdAtom * _name, const char * _fullName)
  7407. : CHqlScope(_op, _name, _fullName)
  7408. {
  7409. }
  7410. void CHqlLocalScope::sethash()
  7411. {
  7412. CHqlScope::sethash();
  7413. }
  7414. bool CHqlLocalScope::equals(const IHqlExpression &r) const
  7415. {
  7416. if (!CHqlExpression::equals(r))
  7417. return false;
  7418. if (!scopesEqual(this, const_cast<IHqlExpression &>(r).queryScope()))
  7419. return false;
  7420. return true;
  7421. }
  7422. IHqlExpression *CHqlLocalScope::clone(HqlExprArray &newkids)
  7423. {
  7424. HqlExprArray syms;
  7425. getSymbols(syms);
  7426. return clone(newkids, syms)->queryExpression();
  7427. }
  7428. IHqlScope * CHqlLocalScope::clone(HqlExprArray & children, HqlExprArray & symbols)
  7429. {
  7430. CHqlScope * cloned = new CHqlLocalScope(op, id, fullName);
  7431. return cloned->cloneAndClose(children, symbols);
  7432. }
  7433. //==============================================================================================================
  7434. /*
  7435. A merged scope is used to make two different scopes (e.g., from two difference sources) appear as one.
  7436. There are several complications (mainly caused by the legacy import semantics):
  7437. a definitions of plugins in earlier scopes take precedence
  7438. b Legacy import needs to get a list of all implicit modules
  7439. c You want to avoid parsing any attributes until actually required.
  7440. d You need to examine the resolved attributes from the scopes to determine if they are implicit
  7441. *
  7442. Unfortunately b,c,d are mutually incompatible. Possibly solutions might be
  7443. a) Don't support legacy any more.
  7444. Nice idea, but not for a couple of years.
  7445. b) only gather implicit modules from the first repository.
  7446. Unfortunately this means archives containing plugins not registered with eclcc no longer compile, which causes
  7447. problems regression testing.w
  7448. c) Ensure all system plugins are parsed (so that (d) works, and allows the parsing short-circuiting to work).
  7449. A bit ugly that you need to remember to do it, but has the advantage of ensuring plugins have no dependencies on
  7450. anything else.
  7451. */
  7452. void CHqlMergedScope::addScope(IHqlScope * scope)
  7453. {
  7454. //This only supports real scopes - it can't be based on modile definitions that could be virtual.
  7455. assertex(!scope->queryExpression()->queryAttribute(_virtualSeq_Atom));
  7456. if (mergedScopes.ordinality())
  7457. {
  7458. const char * name0 = mergedScopes.item(0).queryFullName();
  7459. const char * name1 = scope->queryFullName();
  7460. assertex(name0 == name1 || (name0 && name1 && (stricmp(name0, name1) == 0)));
  7461. }
  7462. mergedScopes.append(*LINK(scope));
  7463. }
  7464. bool CHqlMergedScope::allBasesFullyBound() const
  7465. {
  7466. ForEachItemIn(i, mergedScopes)
  7467. {
  7468. if (!mergedScopes.item(i).allBasesFullyBound())
  7469. return false;
  7470. }
  7471. return true;
  7472. }
  7473. inline bool canMergeDefinition(IHqlExpression * expr)
  7474. {
  7475. IHqlScope * scope = expr->queryScope();
  7476. if (!scope || expr->hasText())
  7477. return false;
  7478. return true;
  7479. }
  7480. IHqlExpression * CHqlMergedScope::lookupSymbol(IIdAtom * searchId, unsigned lookupFlags, HqlLookupContext & ctx)
  7481. {
  7482. CriticalBlock block(cs);
  7483. OwnedHqlExpr resolved = CHqlScope::lookupSymbol(searchId, lookupFlags, ctx);
  7484. if (resolved)
  7485. {
  7486. node_operator resolvedOp = resolved->getOperator();
  7487. if (resolvedOp == no_merge_pending)
  7488. {
  7489. if (lookupFlags & LSFrequired)
  7490. throwRecursiveError(searchId);
  7491. return NULL;
  7492. }
  7493. if (resolvedOp == no_merge_nomatch)
  7494. return NULL;
  7495. if (resolvedOp != no_nobody)
  7496. return resolved.getClear();
  7497. }
  7498. else
  7499. {
  7500. if (mergedAll)
  7501. return NULL;
  7502. }
  7503. OwnedHqlExpr recursionGuard = createSymbol(searchId, LINK(mergePendingMarker), ob_exported);
  7504. defineSymbol(LINK(recursionGuard));
  7505. OwnedHqlExpr previousMatch;
  7506. Owned<CHqlMergedScope> mergeScope;
  7507. unsigned prevErrors = ctx.numErrors();
  7508. unsigned symbolFlags = 0;
  7509. ForEachItemIn(i, mergedScopes)
  7510. {
  7511. OwnedHqlExpr matched = mergedScopes.item(i).lookupSymbol(searchId, lookupFlags, ctx);
  7512. if (matched)
  7513. {
  7514. if (!canMergeDefinition(matched))
  7515. {
  7516. if (!previousMatch)
  7517. previousMatch.setown(matched.getClear());
  7518. break;
  7519. }
  7520. if (previousMatch)
  7521. {
  7522. IHqlScope * previousScope = previousMatch->queryScope();
  7523. mergeScope.setown(new CHqlMergedScope(searchId, previousScope->queryFullName()));
  7524. mergeScope->addScope(previousScope);
  7525. }
  7526. //Not so sure about this....
  7527. symbolFlags |= matched->getSymbolFlags();
  7528. if (mergeScope)
  7529. {
  7530. IHqlScope * scope = matched->queryScope();
  7531. mergeScope->addScope(scope);
  7532. }
  7533. else
  7534. previousMatch.setown(matched.getClear());
  7535. }
  7536. else
  7537. {
  7538. //Prevent cascaded errors in attributes which shouldn't have been reachable (e.g., syntax checking)
  7539. if (prevErrors != ctx.numErrors())
  7540. break;
  7541. }
  7542. }
  7543. if (mergeScope)
  7544. {
  7545. OwnedHqlExpr newScope = mergeScope.getClear()->closeExpr();
  7546. IHqlExpression * symbol = createSymbol(searchId, id, LINK(newScope), true, false, symbolFlags);
  7547. defineSymbol(symbol);
  7548. return LINK(symbol);
  7549. }
  7550. if (previousMatch)
  7551. {
  7552. defineSymbol(LINK(previousMatch));
  7553. return previousMatch.getClear();
  7554. }
  7555. //Indicate that no match was found to save work next time.
  7556. defineSymbol(createSymbol(searchId, LINK(mergeNoMatchMarker), ob_exported));
  7557. return NULL;
  7558. }
  7559. //This function is only likely to be called when gathering implicit modules for the legacy option
  7560. void CHqlMergedScope::ensureSymbolsDefined(HqlLookupContext & ctx)
  7561. {
  7562. CriticalBlock block(cs);
  7563. if (mergedAll)
  7564. return;
  7565. ForEachItemIn(iScope, mergedScopes)
  7566. {
  7567. IHqlScope & cur = mergedScopes.item(iScope);
  7568. cur.ensureSymbolsDefined(ctx);
  7569. HqlExprArray scopeSymbols;
  7570. cur.getSymbols(scopeSymbols);
  7571. //Generate a list of symbols from all the merged scopes
  7572. //If the symbol has already been resolved then store that resolved definition
  7573. //If a definition can be merged with one from a previous one insert a named symbol with no body as a placeholder.
  7574. ForEachItemIn(iSym, scopeSymbols)
  7575. {
  7576. IHqlExpression & cur = scopeSymbols.item(iSym);
  7577. IIdAtom * curName = cur.queryId();
  7578. OwnedHqlExpr prev = symbols.getLinkedValue(curName->lower());
  7579. if (prev)
  7580. {
  7581. //Unusual - check that this hasn't already been resolved by a call to lookupSymbol()
  7582. //otherwise recreating a merged scope can cause problems.
  7583. if ((prev->getOperator() != no_mergedscope) && (prev != &cur))
  7584. {
  7585. if (canMergeDefinition(prev))
  7586. {
  7587. //no_nobody means it need to be resolve - either because multiple matches, or because
  7588. //a child scope hasn't resolved it yet.
  7589. if (prev->getOperator() != no_nobody)
  7590. {
  7591. IHqlExpression * newSymbol = createSymbol(curName, id, NULL, true, false, 0);
  7592. defineSymbol(newSymbol);
  7593. }
  7594. }
  7595. }
  7596. }
  7597. else
  7598. defineSymbol(LINK(&cur));
  7599. }
  7600. }
  7601. mergedAll = true;
  7602. }
  7603. bool CHqlMergedScope::isImplicit() const
  7604. {
  7605. //If implicit only the first scope will count.
  7606. if (mergedScopes.ordinality())
  7607. return mergedScopes.item(0).isImplicit();
  7608. return false;
  7609. }
  7610. bool CHqlMergedScope::isPlugin() const
  7611. {
  7612. //If a plugin only the first scope will count.
  7613. if (mergedScopes.ordinality())
  7614. return mergedScopes.item(0).isPlugin();
  7615. return false;
  7616. }
  7617. //==============================================================================================================
  7618. CHqlLibraryInstance::CHqlLibraryInstance(IHqlExpression * _funcdef, HqlExprArray &parms) : CHqlScope(no_libraryscopeinstance), scopeFunction(_funcdef)
  7619. {
  7620. assertex(scopeFunction->getOperator() == no_funcdef);
  7621. libraryScope = scopeFunction->queryChild(0)->queryScope();
  7622. ForEachItemIn(i, parms)
  7623. addOperand(&parms.item(i));
  7624. parms.kill(true);
  7625. }
  7626. IHqlExpression * CHqlLibraryInstance::clone(HqlExprArray & children)
  7627. {
  7628. return createLibraryInstance(LINK(scopeFunction), children);
  7629. }
  7630. IHqlScope * CHqlLibraryInstance::clone(HqlExprArray & children, HqlExprArray & symbols)
  7631. {
  7632. throwUnexpected();
  7633. return clone(children)->queryScope();
  7634. }
  7635. IHqlExpression *CHqlLibraryInstance::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  7636. {
  7637. OwnedHqlExpr ret = libraryScope->lookupSymbol(searchName, lookupFlags, ctx);
  7638. if (!ret)
  7639. return NULL;
  7640. if (!ret->isExported())
  7641. return ret.getClear();
  7642. //Not sure about following:
  7643. if ((lookupFlags & LSFignoreBase))
  7644. return ret.getClear();
  7645. return createDelayedReference(no_libraryselect, this, ret, lookupFlags, ctx);
  7646. }
  7647. IHqlExpression * createLibraryInstance(IHqlExpression * scopeFunction, HqlExprArray &operands)
  7648. {
  7649. return (new CHqlLibraryInstance(scopeFunction, operands))->closeExpr();
  7650. }
  7651. bool CHqlLibraryInstance::equals(const IHqlExpression & other) const
  7652. {
  7653. if (!CHqlExpression::equals(other))
  7654. return false;
  7655. if (queryExternalDefinition() != other.queryExternalDefinition())
  7656. return false;
  7657. return true;
  7658. }
  7659. void CHqlLibraryInstance::sethash()
  7660. {
  7661. CHqlScope::sethash();
  7662. HASHFIELD(scopeFunction);
  7663. }
  7664. //==============================================================================================================
  7665. //Each function instance needs to have a unique set of parameters
  7666. static IHqlExpression * cloneFunction(IHqlExpression * expr)
  7667. {
  7668. if (expr->getOperator() != no_funcdef)
  7669. return LINK(expr);
  7670. IHqlExpression * formals = expr->queryChild(1);
  7671. if (formals->numChildren() == 0)
  7672. return LINK(expr);
  7673. QuickExpressionReplacer replacer;
  7674. ForEachChild(i, formals)
  7675. {
  7676. IHqlExpression * formal = formals->queryChild(i);
  7677. unsigned seq = (unsigned)formal->querySequenceExtra();
  7678. HqlExprArray attrs;
  7679. unwindChildren(attrs, formal);
  7680. OwnedHqlExpr newFormal = createParameter(formal->queryId(), seq, formal->getType(), attrs);
  7681. assertex(formal != newFormal || seq == UnadornedParameterIndex);
  7682. replacer.setMapping(formal, newFormal);
  7683. }
  7684. return replacer.transform(expr);
  7685. }
  7686. IHqlExpression * createDelayedReference(node_operator op, IHqlExpression * moduleMarker, IHqlExpression * attr, unsigned lookupFlags, HqlLookupContext & ctx)
  7687. {
  7688. IHqlExpression * record = queryOriginalRecord(attr);
  7689. if (!record)
  7690. record = queryNullRecord();
  7691. HqlExprArray args;
  7692. args.append(*LINK(record));
  7693. args.append(*LINK(moduleMarker));
  7694. args.append(*LINK(attr));
  7695. args.append(*createOpenNamedValue(no_attrname, makeVoidType(), attr->queryId())->closeExpr());
  7696. if (lookupFlags & LSFignoreBase)
  7697. args.append(*createAttribute(ignoreBaseAtom));
  7698. if (isGrouped(attr))
  7699. args.append(*createAttribute(groupedAtom));
  7700. OwnedHqlExpr ret;
  7701. if (attr->isFunction())
  7702. ret.setown(createValue(op, attr->getType(), args));
  7703. else if (attr->isDataset())
  7704. ret.setown(createDataset(op, args));
  7705. else if (attr->isDatarow())
  7706. ret.setown(createRow(op, args));
  7707. else
  7708. ret.setown(createValue(op, attr->getType(), args));
  7709. if (attr->isScope())
  7710. {
  7711. if (attr->getOperator() != no_funcdef)
  7712. ret.setown(createDelayedScope(ret.getClear()));
  7713. }
  7714. return attr->cloneAllAnnotations(ret);
  7715. }
  7716. //---------------------------------------------------------------------------------------------------------------------
  7717. class VirtualSymbolReplacer : public QuickHqlTransformer
  7718. {
  7719. public:
  7720. VirtualSymbolReplacer(HqlTransformerInfo & _info, IErrorReceiver * _errors, IHqlExpression * _searchModule)
  7721. : QuickHqlTransformer(_info, _errors)
  7722. {
  7723. visited.setown(createAttribute(alreadyVisitedAtom));
  7724. searchModule = _searchModule;
  7725. }
  7726. virtual IHqlExpression * transform(IHqlExpression * expr)
  7727. {
  7728. #ifdef TRANSFORM_STATS
  7729. stats.beginTransform();
  7730. #endif
  7731. IHqlExpression * match = static_cast<IHqlExpression *>(expr->queryTransformExtra());
  7732. if (match)
  7733. {
  7734. if (match == visited)
  7735. {
  7736. IIdAtom * id = expr->queryId();
  7737. const char * idText = id ? id->str() : "";
  7738. ECLlocation loc(searchModule->queryAttribute(_location_Atom));
  7739. reportError(errors, HQLERR_CycleWithModuleDefinition, loc, HQLERR_CycleWithModuleDefinition_Text, idText);
  7740. }
  7741. #ifdef TRANSFORM_STATS
  7742. stats.endMatchTransform(expr, match);
  7743. #endif
  7744. return LINK(match);
  7745. }
  7746. IHqlExpression * ret;
  7747. if (containsInternalSelect(expr))
  7748. {
  7749. expr->setTransformExtraUnlinked(visited);
  7750. ret = createTransformed(expr);
  7751. }
  7752. else
  7753. ret = LINK(expr);
  7754. #ifdef TRANSFORM_STATS
  7755. stats.endNewTransform(expr, ret);
  7756. #endif
  7757. expr->setTransformExtra(ret);
  7758. return ret;
  7759. }
  7760. virtual IHqlExpression * createTransformedBody(IHqlExpression * expr)
  7761. {
  7762. node_operator op = expr->getOperator();
  7763. switch (op)
  7764. {
  7765. case no_unboundselect:
  7766. throwUnexpected();
  7767. case no_internalselect:
  7768. if (expr->queryChild(1) == searchModule)
  7769. {
  7770. IIdAtom * id = expr->queryChild(3)->queryId();
  7771. return getVirtualReplacement(id);
  7772. }
  7773. break;
  7774. }
  7775. return QuickHqlTransformer::createTransformedBody(expr);
  7776. }
  7777. protected:
  7778. virtual IHqlExpression * getVirtualReplacement(IIdAtom * id) = 0;
  7779. protected:
  7780. OwnedHqlExpr visited;
  7781. IHqlExpression * searchModule;
  7782. };
  7783. //---------------------------------------------------------------------------------------------------------------------
  7784. static HqlTransformerInfo concreteVirtualSymbolReplacerInfo("ConcreteVirtualSymbolReplacer");
  7785. class ConcreteVirtualSymbolReplacer : public VirtualSymbolReplacer
  7786. {
  7787. public:
  7788. ConcreteVirtualSymbolReplacer(IErrorReceiver * _errors, IHqlExpression * _searchModule, SymbolTable & _symbols)
  7789. : VirtualSymbolReplacer(concreteVirtualSymbolReplacerInfo, _errors, _searchModule), symbols(_symbols)
  7790. {
  7791. }
  7792. virtual IHqlExpression * getVirtualReplacement(IIdAtom * name)
  7793. {
  7794. OwnedHqlExpr value = symbols.getLinkedValue(name->lower());
  7795. return transform(value);
  7796. }
  7797. protected:
  7798. SymbolTable & symbols;
  7799. };
  7800. //---------------------------------------------------------------------------------------------------------------------
  7801. static HqlTransformerInfo parameterVirtualSymbolReplacerInfo("ParameterVirtualSymbolReplacer");
  7802. class ParameterVirtualSymbolReplacer : public VirtualSymbolReplacer
  7803. {
  7804. public:
  7805. ParameterVirtualSymbolReplacer(HqlLookupContext & _ctx, IHqlScope * _paramScope, IHqlExpression * _virtualAttribute, unsigned _lookupFlags)
  7806. : VirtualSymbolReplacer(concreteVirtualSymbolReplacerInfo, _ctx.errs, _virtualAttribute),
  7807. ctx(_ctx), paramScope(_paramScope), lookupFlags(_lookupFlags)
  7808. {
  7809. }
  7810. virtual IHqlExpression * getVirtualReplacement(IIdAtom * id)
  7811. {
  7812. return paramScope->lookupSymbol(id, lookupFlags, ctx);
  7813. }
  7814. protected:
  7815. HqlLookupContext & ctx;
  7816. IHqlScope * paramScope;
  7817. unsigned lookupFlags;
  7818. };
  7819. //---------------------------------------------------------------------------------------------------------------------
  7820. /*
  7821. Modules, members, scopes and virtual members.
  7822. ECL allows some modules to be "virtual"
  7823. - MODULE,VIRTUAL and INTERFACE indicate that every member within that module is virtual
  7824. - EXPORT VIRTUAL and SHARED VIRTUAL before a definition mark that definition as virtual
  7825. - If an EXPORTED of SHARED symbol is VIRTUAL in a base module it is virtual in this module.
  7826. Each module that contains any virtuals has a unique virtualSeq attribute associated with it.
  7827. While a virtual module is being defined it is marked as incomplete:
  7828. * When defining a member of a virtual class, references to other members of the class need to be delayed. (The might
  7829. be redefined in this module, or in a module that inherits from this one.)
  7830. This is done by adding an expression no_internalselect(virtual-attribute, <resolved-member>, flags, ...)
  7831. - <resolved> is used for the name and for the type - its value is not used.
  7832. * Whenever a member is selected from an incomplete module it must be a reference from one of its own members, so
  7833. lookupSymbol() returns an expression in this form.
  7834. * Some types of expressions (e.g., records) must currently be returned as no_record and can't be delayed. In this case
  7835. the value is returned (along with no_internalselects for members it references).
  7836. When a module is completed *in the parser* the following happens:
  7837. * Any definitions that haven't been overridden are extracted from the base modules.
  7838. o If the base module is unbound then create a no_unboundselect as a delayed reference.
  7839. o If the base definition is non-virtual, inherit the same definition (add test!)
  7840. o Otherwise use the definition from the base with the base module's virtual uid replaced with references
  7841. to the current module's virtual uid. [definition could also be unbound or undefined]
  7842. o If the definition is defined in multiple base classes ambiguously then complain.
  7843. (An alternative would be to convert it to a no_purevirtual definition and allow it to be overridden later.)
  7844. o If some definitions are no_unboundselect then add a $hasUnknownBase internal attribute.
  7845. - NOTE: Issue HPCC-9325 proposes changing the way inherited members are processed.
  7846. When a module expression is closed:
  7847. * If all bases are bound:
  7848. o If the module has a $hasUnknownBase attribute then re-resolve all no_unboundselect definitions, and remove the attribute.
  7849. Parameters:
  7850. * A parameter needs to be projected to the type of the argument to avoid symbols in a derived module from clashing
  7851. with those defined inside the function. (Stops the interface becoming polluted with new names).
  7852. * Could get syntax errors from incompatible definitions (e.g., derived from parameter) and derived argument.
  7853. The concrete module is created on demand if the module is not abstract.
  7854. When a value is retrieved from a virtual module the following happens:
  7855. * If being accessed from a derived module just return the definition
  7856. * If has a concrete value then return it.
  7857. * If it doesn't have any unbound bases then it is an error accessing an abstract class.
  7858. * If the type of the value cannot be virtual
  7859. o return the value with all no_internalselects and no_unboundselects recursively expanded as no_delayedselects.
  7860. * Create no_assertconcrete node for the current scope. - may not be needed.
  7861. Create a no_delayedselect(<asserted-concrete>, <resolved-member>, flags, ...)
  7862. Delayedselects/internalselects
  7863. * Create a <op>(scope, <resolved-member>, flags, ...)
  7864. * If results is a module wrap it in a no_delayedscope
  7865. * If it is a function.....then it will create a CHqlDelayedCall
  7866. The following opcodes are used
  7867. no_internalselect - a reference to another member within the same module definition
  7868. no_unboundselect - a reference to a member in a base module definition that is currently unbound.
  7869. no_delayedselect - a (delayed) reference to a member in another module.
  7870. no_purevirtual - a member that has no associated definition.
  7871. */
  7872. bool canBeDelayed(IHqlExpression * expr)
  7873. {
  7874. switch (expr->getOperator())
  7875. {
  7876. //The fewer entries in here the better
  7877. case no_enum:
  7878. case no_typedef:
  7879. case no_macro:
  7880. case no_record: // LEFT has problems because queryRecord() is the unbound funcdef
  7881. case no_keyindex: // BUILD() and other functions a reliant on this being expanded out
  7882. case no_newkeyindex:
  7883. return false;
  7884. case no_funcdef:
  7885. return canBeDelayed(expr->queryChild(0));
  7886. }
  7887. return true;
  7888. }
  7889. bool canBeVirtual(IHqlExpression * expr)
  7890. {
  7891. switch (expr->getOperator())
  7892. {
  7893. case no_record:
  7894. case no_enum:
  7895. case no_typedef:
  7896. case no_type:
  7897. case no_macro:
  7898. return false;
  7899. case no_virtualscope:
  7900. case no_delayedscope:
  7901. case no_call:
  7902. return true;
  7903. case no_concretescope:
  7904. case no_libraryscope:
  7905. case no_libraryscopeinstance:
  7906. case no_forwardscope:
  7907. return false;
  7908. case no_scope:
  7909. throwUnexpected();
  7910. case no_funcdef:
  7911. return canBeVirtual(expr->queryChild(0));
  7912. }
  7913. assertex(!expr->isScope());
  7914. return true;
  7915. }
  7916. CHqlVirtualScope::CHqlVirtualScope(IIdAtom * _name, const char * _fullName)
  7917. : CHqlScope(no_virtualscope, _name, _fullName)
  7918. {
  7919. isAbstract = false;
  7920. complete = false;
  7921. containsVirtual = false;
  7922. allVirtual = false;
  7923. fullyBoundBase =true;
  7924. }
  7925. IHqlExpression *CHqlVirtualScope::addOperand(IHqlExpression * arg)
  7926. {
  7927. if (arg->isAttribute())
  7928. {
  7929. IAtom * name = arg->queryName();
  7930. if (name == _virtualSeq_Atom)
  7931. {
  7932. if (arg->querySequenceExtra() == 0)
  7933. {
  7934. //create a virtual attribute with a unique id.
  7935. ensureVirtualSeq();
  7936. arg->Release();
  7937. return this;
  7938. }
  7939. assertex(!hasAttribute(_virtualSeq_Atom));
  7940. containsVirtual = true;
  7941. }
  7942. else if (name == interfaceAtom || name == virtualAtom)
  7943. {
  7944. ensureVirtualSeq();
  7945. isAbstract = (name == interfaceAtom);
  7946. allVirtual = true;
  7947. }
  7948. }
  7949. else if (arg->isScope())
  7950. {
  7951. if (arg->hasAttribute(_virtualSeq_Atom))
  7952. ensureVirtualSeq();
  7953. else if (arg->getOperator() == no_param)
  7954. ensureVirtualSeq(); // yuk- needs another member function.
  7955. if (!areAllBasesFullyBound(arg))
  7956. fullyBoundBase = false;
  7957. }
  7958. return CHqlScope::addOperand(arg);
  7959. }
  7960. static UniqueSequenceCounter virtualSequence;
  7961. void CHqlVirtualScope::ensureVirtualSeq()
  7962. {
  7963. if (!containsVirtual)
  7964. {
  7965. CHqlScope::addOperand(createSequence(no_attr, makeNullType(), _virtualSeq_Atom, virtualSequence.next()));
  7966. containsVirtual = true;
  7967. }
  7968. }
  7969. void CHqlVirtualScope::sethash()
  7970. {
  7971. complete = true;
  7972. CHqlScope::sethash();
  7973. }
  7974. bool CHqlVirtualScope::equals(const IHqlExpression &r) const
  7975. {
  7976. if (!CHqlExpression::equals(r))
  7977. return false;
  7978. if (!scopesEqual(this, const_cast<IHqlExpression &>(r).queryScope()))
  7979. return false;
  7980. return true;
  7981. }
  7982. IHqlExpression *CHqlVirtualScope::clone(HqlExprArray &newkids)
  7983. {
  7984. assertex(false);
  7985. Link();
  7986. return this;
  7987. }
  7988. IHqlScope * CHqlVirtualScope::clone(HqlExprArray & children, HqlExprArray & symbols)
  7989. {
  7990. CHqlScope * cloned = new CHqlVirtualScope(id, fullName);
  7991. return cloned->cloneAndClose(children, symbols);
  7992. }
  7993. extern HQL_API bool isVirtualSymbol(IHqlExpression * expr)
  7994. {
  7995. IHqlNamedAnnotation * symbol = static_cast<IHqlNamedAnnotation *>(expr->queryAnnotation());
  7996. if (symbol && symbol->getAnnotationKind() == annotate_symbol)
  7997. return symbol->isVirtual();
  7998. return false;
  7999. }
  8000. void CHqlVirtualScope::defineSymbol(IHqlExpression * expr)
  8001. {
  8002. #ifdef ALL_MODULE_ATTRS_VIRTUAL
  8003. ensureVirtual(); // remove if we want it to be conditional on an attribute
  8004. #endif
  8005. if (isPureVirtual(expr))
  8006. {
  8007. isAbstract = true;
  8008. ensureVirtualSeq(); // a little bit too late... but probably good enough. should be an error if not virtual.
  8009. }
  8010. else
  8011. {
  8012. if (isVirtualSymbol(expr))
  8013. {
  8014. ensureVirtualSeq();
  8015. }
  8016. else
  8017. {
  8018. //MORE: If this is virtual in the base class then it is an error if virtual flag not set
  8019. }
  8020. }
  8021. CHqlScope::defineSymbol(expr);
  8022. }
  8023. bool CHqlVirtualScope::queryForceSymbolVirtual(IIdAtom * searchName, HqlLookupContext & ctx)
  8024. {
  8025. if (allVirtual)
  8026. return true;
  8027. IHqlExpression * definitionModule = NULL;
  8028. OwnedHqlExpr match = lookupBaseSymbol(definitionModule, searchName, LSFsharedOK, ctx);
  8029. if (match)
  8030. {
  8031. IHqlNamedAnnotation * symbol = static_cast<IHqlNamedAnnotation *>(match->queryAnnotation());
  8032. assertex(symbol && symbol->getAnnotationKind() == annotate_symbol);
  8033. return symbol->isVirtual();
  8034. }
  8035. return false;
  8036. }
  8037. IHqlExpression * CHqlVirtualScope::lookupBaseSymbol(IHqlExpression * & definitionModule, IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8038. {
  8039. ForEachChild(i, this)
  8040. {
  8041. IHqlExpression * child = queryChild(i);
  8042. IHqlScope * base = child->queryScope();
  8043. if (base)
  8044. {
  8045. IHqlExpression * match = base->lookupSymbol(searchName, lookupFlags|LSFfromderived, ctx);
  8046. if (match)
  8047. {
  8048. definitionModule = child;
  8049. return match;
  8050. }
  8051. }
  8052. }
  8053. return NULL;
  8054. }
  8055. IHqlExpression *CHqlVirtualScope::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8056. {
  8057. //Are we just trying to find out what the definition in this scope is?
  8058. if (lookupFlags & LSFignoreBase)
  8059. return CHqlScope::lookupSymbol(searchName, lookupFlags, ctx);
  8060. //The scope is complete=>this is a reference from outside the scope
  8061. if (complete)
  8062. {
  8063. //NOTE: If the members are virtual, then all that is significant is whether a match exists or not.
  8064. if (concrete && !(lookupFlags & LSFfromderived))
  8065. return concrete->lookupSymbol(searchName, lookupFlags, ctx);
  8066. //The class is not concrete...
  8067. //1. It is based on a parameter, and not complete because the parameter hasn't been substituted.
  8068. //2. A reference from a derived module accessing the base definition.
  8069. //3. An illegal access to a member of an abstract class
  8070. OwnedHqlExpr match = CHqlScope::lookupSymbol(searchName, lookupFlags, ctx);
  8071. if (!match)
  8072. return NULL;
  8073. if (!containsVirtual || (lookupFlags & LSFfromderived))
  8074. return match.getClear();
  8075. if (!isVirtualSymbol(match))
  8076. {
  8077. //Select from a parameter where the item is not defined in the parameter's scope => error
  8078. if (match->getOperator() == no_unboundselect)
  8079. throwError1(HQLERR_MemberXContainsVirtualRef, searchName->str());
  8080. if (containsInternalSelect(match))
  8081. {
  8082. //All internal references need to be recursively replaced with no_delayedselect
  8083. //e.g., if fields used to provide default values for records.
  8084. ParameterVirtualSymbolReplacer replacer(ctx, this, queryAttribute(_virtualSeq_Atom), LSFsharedOK);
  8085. return replacer.transform(match);
  8086. }
  8087. return match.getClear();
  8088. }
  8089. assertex(canBeVirtual(match));
  8090. match.setown(createDelayedReference(no_delayedselect, this, match, lookupFlags, ctx));
  8091. //module.x can be used for accessing a member of a base module - even if it is abstract
  8092. return match.getClear();
  8093. }
  8094. //check to see if it is defined in the current module
  8095. OwnedHqlExpr match = CHqlScope::lookupSymbol(searchName, lookupFlags, ctx);
  8096. IHqlExpression * definitionModule = this;
  8097. if (!match)
  8098. match.setown(lookupBaseSymbol(definitionModule, searchName, lookupFlags, ctx));
  8099. if (match)
  8100. {
  8101. if (!containsVirtual)
  8102. return match.getClear();
  8103. if (!isVirtualSymbol(match))
  8104. {
  8105. //Select from a parameter where the item is not defined in the parameter's scope => error
  8106. node_operator matchOp = match->getOperator();
  8107. if (matchOp == no_unboundselect || matchOp == no_purevirtual)
  8108. throwError1(HQLERR_MemberXContainsVirtualRef, searchName->str());
  8109. if (containsInternalSelect(match))
  8110. {
  8111. //throwError1(HQLERR_MemberXContainsVirtualRef, searchName->str());
  8112. //All internal references need to be recursively replaced with no_internalselect
  8113. //e.g., if fields used to provide default values for records.
  8114. ParameterVirtualSymbolReplacer replacer(ctx, this, definitionModule->queryAttribute(_virtualSeq_Atom), LSFsharedOK|LSFfromderived);
  8115. return replacer.transform(match);
  8116. }
  8117. return match.getClear();
  8118. }
  8119. assertex(canBeVirtual(match));
  8120. //References to "virtual" members are always represented with a delayed reference,
  8121. //so that the correct definition will be used.
  8122. return createDelayedReference(no_internalselect, queryAttribute(_virtualSeq_Atom), match, lookupFlags, ctx);
  8123. }
  8124. return NULL;
  8125. }
  8126. IHqlExpression * CHqlVirtualScope::closeExpr()
  8127. {
  8128. if (containsVirtual && !isAbstract && fullyBoundBase)
  8129. {
  8130. resolveUnboundSymbols();
  8131. concrete.setown(deriveConcreteScope());
  8132. if (!containsInternalSelect(concrete->queryExpression()))
  8133. infoFlags &= ~HEFinternalSelect;
  8134. }
  8135. return CHqlScope::closeExpr();
  8136. }
  8137. IHqlScope * CHqlVirtualScope::deriveConcreteScope()
  8138. {
  8139. Owned<IHqlScope> scope = createConcreteScope();
  8140. IHqlExpression * scopeExpr = scope->queryExpression();
  8141. ForEachChild(i, this)
  8142. scopeExpr->addOperand(LINK(queryChild(i)));
  8143. //begin scope
  8144. {
  8145. ConcreteVirtualSymbolReplacer replacer(NULL, queryAttribute(_virtualSeq_Atom), symbols);
  8146. SymbolTableIterator iter(symbols);
  8147. ForEach(iter)
  8148. {
  8149. IHqlExpression *cur = symbols.mapToValue(&iter.query());
  8150. OwnedHqlExpr mapped = replacer.transform(cur);
  8151. OwnedHqlExpr rebound = cloneFunction(mapped);
  8152. scope->defineSymbol(rebound.getClear());
  8153. }
  8154. }
  8155. return scope.getClear()->queryExpression()->closeExpr()->queryScope();
  8156. }
  8157. void CHqlVirtualScope::resolveUnboundSymbols()
  8158. {
  8159. IHqlExpression * virtualAttr = queryAttribute(_virtualSeq_Atom);
  8160. Owned<IErrorReceiver> errorReporter = createThrowingErrorReceiver();
  8161. HqlDummyLookupContext localCtx(errorReporter);
  8162. SymbolTableIterator iter(symbols);
  8163. HqlExprArray defines;
  8164. ForEach(iter)
  8165. {
  8166. IHqlExpression *cur = symbols.mapToValue(&iter.query());
  8167. if (cur->getOperator() == no_unboundselect)
  8168. {
  8169. IIdAtom * searchName = cur->queryId();
  8170. OwnedHqlExpr match;
  8171. ForEachChild(i, this)
  8172. {
  8173. IHqlExpression * child = queryChild(i);
  8174. IHqlScope * base = child->queryScope();
  8175. if (base)
  8176. {
  8177. OwnedHqlExpr resolved = base->lookupSymbol(searchName, LSFsharedOK|LSFfromderived, localCtx);
  8178. if (resolved)
  8179. {
  8180. //Select from a parameter where the item is not defined in the parameter's scope => error
  8181. node_operator resolvedOp = resolved->getOperator();
  8182. if (resolvedOp == no_unboundselect || resolvedOp == no_purevirtual)
  8183. throwError1(HQLERR_MemberXContainsVirtualRef, searchName->str());
  8184. match.setown(quickFullReplaceExpression(resolved, child->queryAttribute(_virtualSeq_Atom), virtualAttr));
  8185. break;
  8186. }
  8187. }
  8188. }
  8189. assertex(match);
  8190. defines.append(*match.getClear());
  8191. }
  8192. }
  8193. //Define the symbols after the iterator so the hash table isn't invalidated
  8194. ForEachItemIn(i, defines)
  8195. defineSymbol(LINK(&defines.item(i)));
  8196. }
  8197. //==============================================================================================================
  8198. class CHqlForwardScope : public CHqlVirtualScope, public IHasUnlinkedOwnerReference
  8199. {
  8200. public:
  8201. CHqlForwardScope(IHqlScope * _parentScope, HqlGramCtx * _parentCtx, HqlParseContext & parseCtx);
  8202. ~CHqlForwardScope()
  8203. {
  8204. assertex(!parentScope);
  8205. }
  8206. IMPLEMENT_IINTERFACE_USING(CHqlVirtualScope)
  8207. virtual void clearOwner()
  8208. {
  8209. if (parentScope)
  8210. {
  8211. resolvedAll = true;
  8212. parentCtx.clear();
  8213. parentScope = NULL;
  8214. }
  8215. }
  8216. virtual void defineSymbol(IHqlExpression * expr);
  8217. virtual IHqlExpression *lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx);
  8218. virtual IHqlScope * queryResolvedScope(HqlLookupContext * context);
  8219. protected:
  8220. IHqlScope * parentScope;
  8221. Owned<HqlGramCtx> parentCtx;
  8222. Owned<IHqlScope> resolved;
  8223. bool resolvedAll;
  8224. };
  8225. //error if !fullBoundBase || isVirtual
  8226. CHqlForwardScope::CHqlForwardScope(IHqlScope * _parentScope, HqlGramCtx * _parentCtx, HqlParseContext & parseCtx)
  8227. : CHqlVirtualScope(NULL, NULL), parentScope(_parentScope), parentCtx(_parentCtx)
  8228. {
  8229. //Need to register this foward reference otherwise circular reference means it will never get deleted.
  8230. parseCtx.addForwardReference(parentScope, this);
  8231. op = no_forwardscope;
  8232. assertex(parentScope);
  8233. //Until we've resolved the contents we have no idea if it is fully bound!
  8234. if (parentCtx->hasAnyActiveParameters())
  8235. infoFlags |= HEFunbound;
  8236. resolved.setown(createVirtualScope(NULL, NULL));
  8237. IHqlExpression * resolvedScopeExpr = resolved->queryExpression();
  8238. ForEachChild(i, this)
  8239. resolvedScopeExpr->addOperand(LINK(queryChild(i)));
  8240. resolvedAll = false;
  8241. }
  8242. void CHqlForwardScope::defineSymbol(IHqlExpression * expr)
  8243. {
  8244. if (expr->queryBody())
  8245. resolved->defineSymbol(expr);
  8246. else
  8247. CHqlVirtualScope::defineSymbol(expr);
  8248. }
  8249. IHqlExpression *CHqlForwardScope::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8250. {
  8251. OwnedHqlExpr resolvedSym = resolved->lookupSymbol(searchName, lookupFlags, ctx);
  8252. if (resolvedSym && resolvedSym->getOperator() == no_processing)
  8253. return NULL;
  8254. if (!(lookupFlags & LSFignoreBase))
  8255. {
  8256. if (resolvedSym || resolvedAll)
  8257. return resolvedSym.getClear();
  8258. }
  8259. OwnedHqlExpr ret = CHqlScope::lookupSymbol(searchName, lookupFlags, ctx);
  8260. if (!ret || (lookupFlags & LSFignoreBase))
  8261. return ret.getClear();
  8262. //MORE: If we had multi-threaded parsing this might cause issues.
  8263. if (!parentScope)
  8264. return NULL;
  8265. IHqlExpression * processingSymbol = createSymbol(searchName, LINK(processingMarker), ob_exported);
  8266. resolved->defineSymbol(processingSymbol);
  8267. bool ok = parseForwardModuleMember(*parentCtx, this, ret, ctx);
  8268. OwnedHqlExpr newSymbol = resolved->lookupSymbol(searchName, lookupFlags, ctx);
  8269. if(!ok || !newSymbol || (newSymbol == processingSymbol))
  8270. {
  8271. IHqlNamedAnnotation * oldSymbol = queryNameAnnotation(ret);
  8272. assertex(oldSymbol);
  8273. resolved->removeSymbol(searchName);
  8274. const char * filename = parentCtx->sourcePath->str();
  8275. StringBuffer msg("Definition must contain EXPORT or SHARED value for ");
  8276. msg.append(*searchName);
  8277. throw createECLError(ERR_EXPORT_OR_SHARE, msg.toCharArray(), filename, oldSymbol->getStartLine(), oldSymbol->getStartColumn(), 1);
  8278. }
  8279. if (!(newSymbol->isExported() || (lookupFlags & LSFsharedOK)))
  8280. return NULL;
  8281. return newSymbol.getClear();
  8282. }
  8283. IHqlScope * CHqlForwardScope::queryResolvedScope(HqlLookupContext * context)
  8284. {
  8285. if (!resolvedAll)
  8286. {
  8287. //Generally we should have a lookup context passed in so the archive is updated correctly
  8288. //But currently painful in one context, so allow it to be omitted.
  8289. Owned<IErrorReceiver> errorReporter = createThrowingErrorReceiver();
  8290. HqlDummyLookupContext localCtx(errorReporter);
  8291. HqlLookupContext * activeContext = context ? context : &localCtx;
  8292. HqlExprArray syms;
  8293. getSymbols(syms);
  8294. syms.sort(compareSymbolsByName); // Make errors consistent
  8295. ForEachItemIn(i, syms)
  8296. {
  8297. IIdAtom * cur = syms.item(i).queryId();
  8298. ::Release(lookupSymbol(cur, LSFsharedOK, *activeContext));
  8299. //Could have been fully resolved while looking up a symbol!
  8300. if (resolvedAll)
  8301. return resolved;
  8302. }
  8303. if (!resolvedAll)
  8304. {
  8305. resolved.setown(closeScope(resolved.getClear()));
  8306. resolvedAll = true;
  8307. }
  8308. }
  8309. return resolved;
  8310. }
  8311. void addForwardDefinition(IHqlScope * scope, IIdAtom * symbolName, IIdAtom * moduleName, IFileContents * contents, unsigned symbolFlags, bool isExported, unsigned startLine, unsigned startColumn)
  8312. {
  8313. IHqlExpression * cur = createSymbol(symbolName, moduleName, NULL, NULL,
  8314. isExported, !isExported, symbolFlags,
  8315. contents, startLine, startColumn, 0, 0, 0);
  8316. scope->defineSymbol(cur);
  8317. }
  8318. //==============================================================================================================
  8319. CHqlMultiParentScope::CHqlMultiParentScope(IIdAtom * _name, ...)
  8320. : CHqlScope(no_privatescope, _name, _name->str())
  8321. {
  8322. va_list args;
  8323. va_start(args, _name);
  8324. for (;;)
  8325. {
  8326. IHqlScope *parent = va_arg(args, IHqlScope*);
  8327. if (!parent)
  8328. break;
  8329. //This should only be used for parser scopes (which are real and non virtual).
  8330. IHqlExpression * parentExpr = parent->queryExpression();
  8331. assertex(!parentExpr->hasAttribute(_virtualSeq_Atom));
  8332. parents.append(*parent);
  8333. }
  8334. va_end(args);
  8335. }
  8336. IHqlExpression *CHqlMultiParentScope::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8337. {
  8338. IHqlExpression *ret = CHqlScope::lookupSymbol(searchName, lookupFlags, ctx);
  8339. if (ret)
  8340. return ret;
  8341. unsigned numChildren = parents.length();
  8342. for (unsigned i=0; i<numChildren; i++)
  8343. {
  8344. ret = ((IHqlScope&)parents.item(i)).lookupSymbol(searchName, lookupFlags, ctx);
  8345. if (ret)
  8346. return ret;
  8347. }
  8348. return NULL;
  8349. }
  8350. //==============================================================================================================
  8351. CHqlContextScope::CHqlContextScope(IHqlScope* _scope) : CHqlScope(no_privatescope)
  8352. {
  8353. CHqlContextScope* scope = QUERYINTERFACE(_scope, CHqlContextScope);
  8354. assertex(scope);
  8355. SymbolTableIterator it(scope->defined);
  8356. //StringBuffer debug(" Context:");
  8357. for(it.first();it.isValid();it.next())
  8358. {
  8359. IMapping* name = &it.query();
  8360. IHqlExpression * value = scope->defined.mapToValue(name);
  8361. if(value)
  8362. {
  8363. IIdAtom * valueId = value->queryId();
  8364. //debug.appendf(" %s",name->str());
  8365. defined.setValue(valueId->lower(),value);
  8366. }
  8367. }
  8368. //PrintLog(debug.str());
  8369. }
  8370. //==============================================================================================================
  8371. static UniqueSequenceCounter parameterSequence;
  8372. CHqlParameter::CHqlParameter(IIdAtom * _id, unsigned _idx, ITypeInfo *_type)
  8373. : CHqlExpressionWithType(no_param, _type)
  8374. {
  8375. id = _id;
  8376. idx = _idx;
  8377. infoFlags |= HEFunbound;
  8378. uid = (idx == UnadornedParameterIndex) ? 0 : parameterSequence.next();
  8379. }
  8380. CHqlParameter::~CHqlParameter()
  8381. {
  8382. }
  8383. bool CHqlParameter::equals(const IHqlExpression & _other) const
  8384. {
  8385. if (!CHqlExpression::equals(_other))
  8386. return false;
  8387. const CHqlParameter & other = static_cast<const CHqlParameter &>(_other);
  8388. if (uid != other.uid)
  8389. return false;
  8390. if ((id != other.id) || (idx != other.idx))
  8391. return false;
  8392. return true;
  8393. }
  8394. IHqlExpression * CHqlParameter::makeParameter(IIdAtom * _id, unsigned _idx, ITypeInfo *_type, HqlExprArray & _attrs)
  8395. {
  8396. IHqlExpression * e;
  8397. type_t tc = _type->getTypeCode();
  8398. switch (tc)
  8399. {
  8400. case type_dictionary:
  8401. e = new CHqlDictionaryParameter(_id, _idx, _type);
  8402. break;
  8403. case type_table:
  8404. case type_groupedtable:
  8405. e = new CHqlDatasetParameter(_id, _idx, _type);
  8406. break;
  8407. case type_scope:
  8408. e = new CHqlScopeParameter(_id, _idx, _type);
  8409. break;
  8410. default:
  8411. e = new CHqlParameter(_id, _idx, _type);
  8412. break;
  8413. }
  8414. ForEachItemIn(i, _attrs)
  8415. e->addOperand(LINK(&_attrs.item(i)));
  8416. return e->closeExpr();
  8417. }
  8418. IHqlSimpleScope *CHqlParameter::querySimpleScope()
  8419. {
  8420. ITypeInfo * recordType = ::queryRecordType(type);
  8421. if (!recordType)
  8422. return NULL;
  8423. return QUERYINTERFACE(queryUnqualifiedType(recordType), IHqlSimpleScope);
  8424. }
  8425. void CHqlParameter::sethash()
  8426. {
  8427. CHqlExpression::sethash();
  8428. HASHFIELD(uid);
  8429. HASHFIELD(id);
  8430. HASHFIELD(idx);
  8431. }
  8432. IHqlExpression *CHqlParameter::clone(HqlExprArray &newkids)
  8433. {
  8434. return makeParameter(id, idx, LINK(type), newkids);
  8435. }
  8436. StringBuffer &CHqlParameter::toString(StringBuffer &ret)
  8437. {
  8438. ret.append('%');
  8439. ret.append(id->str());
  8440. ret.append('-');
  8441. ret.append(idx);
  8442. return ret;
  8443. }
  8444. //==============================================================================================================
  8445. CHqlScopeParameter::CHqlScopeParameter(IIdAtom * _id, unsigned _idx, ITypeInfo *_type)
  8446. : CHqlScope(no_param, _id, _id->str())
  8447. {
  8448. type = _type;
  8449. idx = _idx;
  8450. typeScope = ::queryScope(type);
  8451. infoFlags |= HEFunbound;
  8452. uid = (idx == UnadornedParameterIndex) ? 0 : parameterSequence.next();
  8453. if (!hasAttribute(_virtualSeq_Atom))
  8454. addOperand(createSequence(no_attr, makeNullType(), _virtualSeq_Atom, virtualSequence.next()));
  8455. }
  8456. bool CHqlScopeParameter::assignableFrom(ITypeInfo * source)
  8457. {
  8458. return type->assignableFrom(source);
  8459. }
  8460. bool CHqlScopeParameter::equals(const IHqlExpression & _other) const
  8461. {
  8462. if (!CHqlExpression::equals(_other))
  8463. return false;
  8464. const CHqlScopeParameter & other = static_cast<const CHqlScopeParameter &>(_other);
  8465. if (uid != other.uid)
  8466. return false;
  8467. if ((id != other.id) || (idx != other.idx))
  8468. return false;
  8469. return (this == &_other);
  8470. }
  8471. IHqlExpression *CHqlScopeParameter::clone(HqlExprArray &newkids)
  8472. {
  8473. throwUnexpected();
  8474. return createParameter(id, idx, LINK(type), newkids);
  8475. }
  8476. IHqlScope * CHqlScopeParameter::clone(HqlExprArray & children, HqlExprArray & symbols)
  8477. {
  8478. throwUnexpected();
  8479. }
  8480. void CHqlScopeParameter::sethash()
  8481. {
  8482. CHqlScope::sethash();
  8483. HASHFIELD(uid);
  8484. HASHFIELD(id);
  8485. HASHFIELD(idx);
  8486. }
  8487. StringBuffer &CHqlScopeParameter::toString(StringBuffer &ret)
  8488. {
  8489. ret.append('%');
  8490. ret.append(id->str());
  8491. ret.append('-');
  8492. ret.append(idx);
  8493. return ret;
  8494. }
  8495. IHqlExpression * CHqlScopeParameter::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8496. {
  8497. OwnedHqlExpr match = typeScope->lookupSymbol(searchName, lookupFlags|LSFfromderived, ctx);
  8498. if (!match)
  8499. return NULL;
  8500. if (lookupFlags & (LSFignoreBase|LSFfromderived))
  8501. return match.getClear();
  8502. if (!canBeVirtual(match))
  8503. {
  8504. if (containsInternalSelect(match))
  8505. {
  8506. IHqlExpression * typeScopeExpr = ::queryExpression(typeScope);
  8507. ParameterVirtualSymbolReplacer replacer(ctx, this, typeScopeExpr->queryAttribute(_virtualSeq_Atom), LSFsharedOK);
  8508. match.setown(replacer.transform(match));
  8509. }
  8510. return match.getClear();
  8511. }
  8512. return createDelayedReference(no_delayedselect, this, match, lookupFlags, ctx);
  8513. }
  8514. //==============================================================================================================
  8515. CHqlDelayedScope::CHqlDelayedScope(HqlExprArray &_ownedOperands)
  8516. : CHqlExpressionWithTables(no_delayedscope)
  8517. {
  8518. setOperands(_ownedOperands); // after type is initialized
  8519. type = queryChild(0)->queryType();
  8520. ITypeInfo * scopeType = type;
  8521. if (scopeType->getTypeCode() == type_function)
  8522. scopeType = scopeType->queryChildType();
  8523. typeScope = ::queryScope(scopeType);
  8524. assertex(typeScope);
  8525. if (!hasAttribute(_virtualSeq_Atom))
  8526. addOperand(createSequence(no_attr, makeNullType(), _virtualSeq_Atom, virtualSequence.next()));
  8527. }
  8528. bool CHqlDelayedScope::assignableFrom(ITypeInfo * source)
  8529. {
  8530. return type->assignableFrom(source);
  8531. }
  8532. bool CHqlDelayedScope::equals(const IHqlExpression & _other) const
  8533. {
  8534. if (!CHqlExpressionWithTables::equals(_other))
  8535. return false;
  8536. return true;
  8537. }
  8538. IHqlExpression *CHqlDelayedScope::clone(HqlExprArray &newkids)
  8539. {
  8540. return createDelayedScope(newkids);
  8541. }
  8542. IHqlScope * CHqlDelayedScope::clone(HqlExprArray & children, HqlExprArray & symbols)
  8543. {
  8544. throwUnexpected();
  8545. }
  8546. IHqlExpression * CHqlDelayedScope::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8547. {
  8548. IHqlScope * scope = queryChild(0)->queryScope();
  8549. if (scope)
  8550. return scope->lookupSymbol(searchName, lookupFlags, ctx);
  8551. OwnedHqlExpr match = typeScope->lookupSymbol(searchName, lookupFlags, ctx);
  8552. if (!match)
  8553. return NULL;
  8554. if (lookupFlags & LSFignoreBase)
  8555. return match.getClear();
  8556. if (!canBeVirtual(match))
  8557. return match.getClear();
  8558. return createDelayedReference(no_delayedselect, this, match, lookupFlags, ctx);
  8559. }
  8560. void CHqlDelayedScope::ensureSymbolsDefined(HqlLookupContext & ctx)
  8561. {
  8562. }
  8563. void CHqlDelayedScope::getSymbols(HqlExprArray& exprs) const
  8564. {
  8565. typeScope->getSymbols(exprs);
  8566. }
  8567. ITypeInfo * CHqlDelayedScope::queryType() const
  8568. {
  8569. return type;
  8570. }
  8571. ITypeInfo * CHqlDelayedScope::getType()
  8572. {
  8573. return LINK(type);
  8574. }
  8575. bool CHqlDelayedScope::hasBaseClass(IHqlExpression * searchBase)
  8576. {
  8577. return typeScope->hasBaseClass(searchBase);
  8578. }
  8579. IHqlScope * CHqlDelayedScope::queryConcreteScope()
  8580. {
  8581. return NULL;
  8582. }
  8583. IHqlScope * CHqlDelayedScope::queryResolvedScope(HqlLookupContext * context)
  8584. {
  8585. return this;
  8586. }
  8587. IHqlExpression * createDelayedScope(HqlExprArray &newkids)
  8588. {
  8589. CHqlDelayedScope * scope = new CHqlDelayedScope(newkids);
  8590. return scope->closeExpr();
  8591. }
  8592. IHqlExpression * createDelayedScope(IHqlExpression * expr)
  8593. {
  8594. HqlExprArray args;
  8595. args.append(*expr);
  8596. return createDelayedScope(args);
  8597. }
  8598. //==============================================================================================================
  8599. CHqlVariable::CHqlVariable(node_operator _op, const char * _name, ITypeInfo * _type) : CHqlExpressionWithType(_op, _type)
  8600. {
  8601. #ifdef SEARCH_NAME1
  8602. if (strcmp(_name, SEARCH_NAME1) == 0)
  8603. debugMatchedName();
  8604. #endif
  8605. #ifdef SEARCH_NAME2
  8606. if (strcmp(_name, SEARCH_NAME2) == 0)
  8607. debugMatchedName();
  8608. #endif
  8609. name.set(_name);
  8610. infoFlags |= HEFtranslated;
  8611. infoFlags |= HEFhasunadorned;
  8612. }
  8613. CHqlVariable *CHqlVariable::makeVariable(node_operator op, const char * name, ITypeInfo * type)
  8614. {
  8615. CHqlVariable *e = new CHqlVariable(op, name, type);
  8616. return (CHqlVariable *) e->closeExpr();
  8617. }
  8618. bool CHqlVariable::equals(const IHqlExpression & r) const
  8619. {
  8620. if (CHqlExpression::equals(r))
  8621. {
  8622. assertex(QUERYINTERFACE(&r, const CHqlVariable) == (const CHqlVariable *) &r);
  8623. const CHqlVariable *c = (const CHqlVariable *) &r;
  8624. return strcmp(name, c->name) == 0;
  8625. }
  8626. return false;
  8627. }
  8628. void CHqlVariable::sethash()
  8629. {
  8630. CHqlExpression::sethash();
  8631. hashcode = hashc((unsigned char *) name.get(), name.length(), hashcode);
  8632. }
  8633. IHqlExpression *CHqlVariable::clone(HqlExprArray &newkids)
  8634. {
  8635. assertex(newkids.ordinality() == 0); // No operands so there can't be any difference!
  8636. Link();
  8637. return this;
  8638. }
  8639. StringBuffer &CHqlVariable::toString(StringBuffer &ret)
  8640. {
  8641. return ret.append(name);
  8642. }
  8643. //==============================================================================================================
  8644. CHqlAttribute::CHqlAttribute(node_operator _op, IAtom * _name) : CHqlExpressionWithTables(_op)
  8645. {
  8646. name = _name;
  8647. }
  8648. CHqlAttribute *CHqlAttribute::makeAttribute(node_operator op, IAtom * name)
  8649. {
  8650. CHqlAttribute* e = new CHqlAttribute(op, name);
  8651. return e;
  8652. }
  8653. bool CHqlAttribute::equals(const IHqlExpression &r) const
  8654. {
  8655. if (CHqlExpression::equals(r))
  8656. return name==r.queryName();
  8657. return false;
  8658. }
  8659. void CHqlAttribute::sethash()
  8660. {
  8661. CHqlExpression::sethash();
  8662. hashcode = hashc((unsigned char *) &name, sizeof(name), hashcode);
  8663. }
  8664. IHqlExpression *CHqlAttribute::clone(HqlExprArray & args)
  8665. {
  8666. return createAttribute(op, name, args);
  8667. }
  8668. StringBuffer &CHqlAttribute::toString(StringBuffer &ret)
  8669. {
  8670. ret.append(name);
  8671. unsigned kids = numChildren();
  8672. if (kids)
  8673. {
  8674. ret.append('(');
  8675. for (unsigned i=0; i<kids; i++)
  8676. {
  8677. if (i>0)
  8678. ret.append(',');
  8679. queryChild(i)->toString(ret);
  8680. }
  8681. ret.append(')');
  8682. }
  8683. return ret;
  8684. }
  8685. ITypeInfo * CHqlAttribute::queryType() const
  8686. {
  8687. return nullType;
  8688. }
  8689. ITypeInfo * CHqlAttribute::getType()
  8690. {
  8691. return LINK(nullType);
  8692. }
  8693. //==============================================================================================================
  8694. CHqlUnknown::CHqlUnknown(node_operator _op, ITypeInfo * _type, IAtom * _name, IInterface * _extra) : CHqlExpressionWithType(_op, _type)
  8695. {
  8696. name = _name;
  8697. extra.setown(_extra);
  8698. }
  8699. CHqlUnknown *CHqlUnknown::makeUnknown(node_operator _op, ITypeInfo * _type, IAtom * _name, IInterface * _extra)
  8700. {
  8701. if (!_type) _type = makeVoidType();
  8702. return new CHqlUnknown(_op, _type, _name, _extra);
  8703. }
  8704. bool CHqlUnknown::equals(const IHqlExpression &r) const
  8705. {
  8706. if (CHqlExpression::equals(r) && name==r.queryName())
  8707. {
  8708. const CHqlUnknown * other = dynamic_cast<const CHqlUnknown *>(&r);
  8709. if (other && (extra == other->extra))
  8710. return true;
  8711. }
  8712. return false;
  8713. }
  8714. IInterface * CHqlUnknown::queryUnknownExtra()
  8715. {
  8716. return extra;
  8717. }
  8718. void CHqlUnknown::sethash()
  8719. {
  8720. CHqlExpression::sethash();
  8721. hashcode = hashc((unsigned char *) &name, sizeof(name), hashcode);
  8722. hashcode = hashc((unsigned char *) &extra, sizeof(extra), hashcode);
  8723. }
  8724. IHqlExpression *CHqlUnknown::clone(HqlExprArray &newkids)
  8725. {
  8726. assertex(newkids.ordinality() == 0);
  8727. return createUnknown(op, type, name, extra.getLink());
  8728. }
  8729. StringBuffer &CHqlUnknown::toString(StringBuffer &ret)
  8730. {
  8731. return ret.append(name);
  8732. }
  8733. //==============================================================================================================
  8734. CHqlSequence::CHqlSequence(node_operator _op, ITypeInfo * _type, IAtom * _name, unsigned __int64 _seq) : CHqlExpressionWithType(_op, _type)
  8735. {
  8736. infoFlags |= HEFhasunadorned;
  8737. name = _name;
  8738. seq = _seq;
  8739. }
  8740. CHqlSequence *CHqlSequence::makeSequence(node_operator _op, ITypeInfo * _type, IAtom * _name, unsigned __int64 _seq)
  8741. {
  8742. if (!_type) _type = makeNullType();
  8743. return new CHqlSequence(_op, _type, _name, _seq);
  8744. }
  8745. bool CHqlSequence::equals(const IHqlExpression &r) const
  8746. {
  8747. if (CHqlExpression::equals(r) && name==r.queryName())
  8748. {
  8749. const CHqlSequence * other = dynamic_cast<const CHqlSequence *>(&r);
  8750. if (other && (seq == other->seq))
  8751. return true;
  8752. }
  8753. return false;
  8754. }
  8755. void CHqlSequence::sethash()
  8756. {
  8757. CHqlExpression::sethash();
  8758. hashcode = hashc((unsigned char *) &name, sizeof(name), hashcode);
  8759. hashcode = hashc((unsigned char *) &seq, sizeof(seq), hashcode);
  8760. }
  8761. IHqlExpression *CHqlSequence::clone(HqlExprArray &newkids)
  8762. {
  8763. assertex(newkids.ordinality() == 0);
  8764. return LINK(this);
  8765. }
  8766. StringBuffer &CHqlSequence::toString(StringBuffer &ret)
  8767. {
  8768. return ret.append(name);
  8769. }
  8770. //==============================================================================================================
  8771. CHqlExternal::CHqlExternal(IIdAtom * _id, ITypeInfo *_type, HqlExprArray &_ownedOperands) : CHqlExpressionWithType(no_external, _type, _ownedOperands)
  8772. {
  8773. id = _id;
  8774. }
  8775. bool CHqlExternal::equals(const IHqlExpression &r) const
  8776. {
  8777. return (this == &r);
  8778. }
  8779. CHqlExternal *CHqlExternal::makeExternalReference(IIdAtom * _id, ITypeInfo *_type, HqlExprArray &_ownedOperands)
  8780. {
  8781. return new CHqlExternal(_id, _type, _ownedOperands);
  8782. }
  8783. //==============================================================================================================
  8784. CHqlExternalCall::CHqlExternalCall(IHqlExpression * _funcdef, ITypeInfo * _type, HqlExprArray &_ownedOperands) : CHqlExpressionWithType(no_externalcall, _type, _ownedOperands), funcdef(_funcdef)
  8785. {
  8786. IHqlExpression * def = funcdef->queryChild(0);
  8787. //Once aren't really pure, but are as far as the code generator is concerned. Split into more flags if it becomes an issue.
  8788. if (!def->hasAttribute(pureAtom) && !def->hasAttribute(onceAtom))
  8789. {
  8790. infoFlags |= (HEFvolatile);
  8791. }
  8792. if (def->hasAttribute(actionAtom) || (type && type->getTypeCode() == type_void))
  8793. infoFlags |= HEFaction;
  8794. if (def->hasAttribute(userMatchFunctionAtom))
  8795. {
  8796. infoFlags |= HEFcontainsNlpText;
  8797. }
  8798. if (def->hasAttribute(contextSensitiveAtom))
  8799. infoFlags |= HEFcontextDependentException;
  8800. if (def->hasAttribute(ctxmethodAtom) || def->hasAttribute(gctxmethodAtom) || def->hasAttribute(globalContextAtom) || def->hasAttribute(contextAtom))
  8801. infoFlags |= HEFaccessRuntimeContext;
  8802. }
  8803. bool CHqlExternalCall::equals(const IHqlExpression & other) const
  8804. {
  8805. if (this == &other)
  8806. return true;
  8807. if (!CHqlExpression::equals(other))
  8808. return false;
  8809. if (queryExternalDefinition() != other.queryExternalDefinition())
  8810. return false;
  8811. return true;
  8812. }
  8813. IHqlExpression * CHqlExternalCall::queryExternalDefinition() const
  8814. {
  8815. return funcdef;
  8816. }
  8817. void CHqlExternalCall::sethash()
  8818. {
  8819. CHqlExpression::sethash();
  8820. HASHFIELD(funcdef);
  8821. }
  8822. IHqlExpression *CHqlExternalCall::clone(HqlExprArray &newkids)
  8823. {
  8824. if ((newkids.ordinality() == 0) && (operands.ordinality() == 0))
  8825. return LINK(this);
  8826. return makeExternalCall(LINK(funcdef), LINK(type), newkids);
  8827. }
  8828. IHqlExpression * CHqlExternalCall::makeExternalCall(IHqlExpression * _funcdef, ITypeInfo * type, HqlExprArray &_ownedOperands)
  8829. {
  8830. CHqlExternalCall * ret;
  8831. switch (type->getTypeCode())
  8832. {
  8833. case type_table:
  8834. case type_groupedtable:
  8835. ret = new CHqlExternalDatasetCall(_funcdef, type, _ownedOperands);
  8836. break;
  8837. default:
  8838. ret = new CHqlExternalCall(_funcdef, type, _ownedOperands);
  8839. break;
  8840. }
  8841. return ret->closeExpr();
  8842. }
  8843. IHqlExpression *CHqlExternalDatasetCall::clone(HqlExprArray &newkids)
  8844. {
  8845. return makeExternalCall(LINK(funcdef), LINK(type), newkids);
  8846. }
  8847. //==============================================================================================================
  8848. CHqlDelayedCall::CHqlDelayedCall(IHqlExpression * _param, ITypeInfo * _type, HqlExprArray &_ownedOperands) : CHqlExpressionWithType(no_call, _type, _ownedOperands), param(_param)
  8849. {
  8850. infoFlags |= (param->getInfoFlags() & HEFalwaysInherit);
  8851. infoFlags2 |= (param->getInfoFlags2() & HEF2alwaysInherit);
  8852. }
  8853. bool CHqlDelayedCall::equals(const IHqlExpression & _other) const
  8854. {
  8855. if (!CHqlExpression::equals(_other))
  8856. return false;
  8857. const CHqlDelayedCall & other = static_cast<const CHqlDelayedCall &>(_other);
  8858. if (param != other.param)
  8859. return false;
  8860. return true;
  8861. }
  8862. void CHqlDelayedCall::sethash()
  8863. {
  8864. CHqlExpression::sethash();
  8865. HASHFIELD(param);
  8866. }
  8867. IHqlExpression *CHqlDelayedCall::clone(HqlExprArray &newkids)
  8868. {
  8869. return makeDelayedCall(LINK(param), newkids);
  8870. }
  8871. IHqlExpression * CHqlDelayedCall::makeDelayedCall(IHqlExpression * _funcdef, HqlExprArray &operands)
  8872. {
  8873. ITypeInfo * returnType = _funcdef->queryType()->queryChildType();
  8874. CHqlDelayedCall * ret;
  8875. switch (returnType->getTypeCode())
  8876. {
  8877. case type_table:
  8878. case type_groupedtable:
  8879. ret = new CHqlDelayedDatasetCall(_funcdef, LINK(returnType), operands);
  8880. break;
  8881. case type_scope:
  8882. ret = new CHqlDelayedScopeCall(_funcdef, LINK(returnType), operands);
  8883. break;
  8884. default:
  8885. ret = new CHqlDelayedCall(_funcdef, LINK(returnType), operands);
  8886. break;
  8887. }
  8888. return ret->closeExpr();
  8889. }
  8890. //==============================================================================================================
  8891. CHqlDelayedScopeCall::CHqlDelayedScopeCall(IHqlExpression * _param, ITypeInfo * type, HqlExprArray &parms)
  8892. : CHqlDelayedCall(_param, type, parms)
  8893. {
  8894. typeScope = ::queryScope(type); // no need to link
  8895. if (!hasAttribute(_virtualSeq_Atom))
  8896. addOperand(createSequence(no_attr, makeNullType(), _virtualSeq_Atom, virtualSequence.next()));
  8897. }
  8898. IHqlExpression * CHqlDelayedScopeCall::lookupSymbol(IIdAtom * searchName, unsigned lookupFlags, HqlLookupContext & ctx)
  8899. {
  8900. OwnedHqlExpr match = typeScope->lookupSymbol(searchName, lookupFlags, ctx);
  8901. if (!match)
  8902. return NULL;
  8903. if (lookupFlags & LSFignoreBase)
  8904. return match.getClear();
  8905. return createDelayedReference(no_delayedselect, this, match, lookupFlags, ctx);
  8906. }
  8907. void CHqlDelayedScopeCall::getSymbols(HqlExprArray& exprs) const
  8908. {
  8909. typeScope->getSymbols(exprs);
  8910. }
  8911. IHqlScope * CHqlDelayedScopeCall::queryConcreteScope()
  8912. {
  8913. return NULL;
  8914. }
  8915. IAtom * CHqlDelayedScopeCall::queryName() const
  8916. {
  8917. return typeScope->queryName();
  8918. }
  8919. IIdAtom * CHqlDelayedScopeCall::queryId() const
  8920. {
  8921. return typeScope->queryId();
  8922. }
  8923. bool CHqlDelayedScopeCall::hasBaseClass(IHqlExpression * searchBase)
  8924. {
  8925. return typeScope->hasBaseClass(searchBase);
  8926. }
  8927. //==============================================================================================================
  8928. #ifdef _MSC_VER
  8929. #pragma warning( push )
  8930. #pragma warning( disable : 4355 )
  8931. #endif
  8932. /* In parm: scope is linked */
  8933. CHqlAlienType::CHqlAlienType(IIdAtom * _id, IHqlScope *_scope, IHqlExpression * _funcdef) : CHqlExpressionWithTables(no_type)
  8934. {
  8935. id = _id;
  8936. scope = _scope;
  8937. funcdef = _funcdef;
  8938. if (!funcdef)
  8939. funcdef = this;
  8940. IHqlExpression * load = queryLoadFunction();
  8941. IHqlExpression * store = queryStoreFunction();
  8942. assertex(load->getOperator() == no_funcdef && load->queryChild(1)->numChildren()==1);
  8943. assertex(store->getOperator() == no_funcdef && store->queryChild(1)->numChildren()==1);
  8944. IHqlExpression * loadParam = load->queryChild(1)->queryChild(0);
  8945. logical= load->queryType()->queryChildType();
  8946. physical = loadParam->queryType();
  8947. }
  8948. #ifdef _MSC_VER
  8949. #pragma warning( pop )
  8950. #endif
  8951. CHqlAlienType::~CHqlAlienType()
  8952. {
  8953. ::Release(scope);
  8954. if (funcdef != this)
  8955. ::Release(funcdef);
  8956. }
  8957. ITypeInfo * CHqlAlienType::queryType() const
  8958. {
  8959. return const_cast<CHqlAlienType *>(this);
  8960. }
  8961. ITypeInfo * CHqlAlienType::getType()
  8962. {
  8963. CHqlAlienType::Link();
  8964. return this;
  8965. }
  8966. bool CHqlAlienType::equals(const IHqlExpression &r) const
  8967. {
  8968. if (!CHqlExpression::equals(r))
  8969. return false;
  8970. //hack
  8971. return scopesEqual(scope, const_cast<IHqlExpression &>(r).queryScope());
  8972. }
  8973. void CHqlAlienType::sethash()
  8974. {
  8975. // Can't use base class as that includes type (== this) which would make it different every time
  8976. setInitialHash(0);
  8977. }
  8978. unsigned CHqlAlienType::getCardinality()
  8979. {
  8980. //MORE?
  8981. unsigned pcard = physical->getCardinality();
  8982. unsigned lcard = logical->getCardinality();
  8983. if (pcard < lcard)
  8984. return pcard;
  8985. else
  8986. return lcard;
  8987. }
  8988. IHqlExpression *CHqlAlienType::clone(HqlExprArray &newkids)
  8989. {
  8990. IHqlExpression * ret = new CHqlAlienType(id, LINK(scope), LINK(funcdef));
  8991. ForEachItemIn(idx2, newkids)
  8992. ret->addOperand(&OLINK(newkids.item(idx2)));
  8993. return ret->closeExpr();
  8994. }
  8995. unsigned CHqlAlienType::getCrc()
  8996. {
  8997. return getExpressionCRC(this);
  8998. }
  8999. unsigned CHqlAlienType::getMaxSize()
  9000. {
  9001. unsigned size = physical->getSize();
  9002. if (size != UNKNOWN_LENGTH)
  9003. return size;
  9004. OwnedHqlExpr maxSize = lookupSymbol(maxSizeId);
  9005. if (!maxSize)
  9006. maxSize.setown(lookupSymbol(maxLengthId));
  9007. if (maxSize)
  9008. {
  9009. OwnedHqlExpr folded = foldHqlExpression(maxSize);
  9010. if (folded->queryValue())
  9011. return (unsigned)folded->queryValue()->getIntValue();
  9012. }
  9013. return UNKNOWN_LENGTH;
  9014. }
  9015. IHqlExpression *CHqlAlienType::queryFunctionDefinition() const
  9016. {
  9017. return funcdef;
  9018. }
  9019. IHqlExpression * CHqlAlienType::queryLoadFunction()
  9020. {
  9021. return queryMemberFunc(loadId);
  9022. }
  9023. IHqlExpression * CHqlAlienType::queryLengthFunction()
  9024. {
  9025. OwnedHqlExpr func = lookupSymbol(physicalLengthId);
  9026. assertex(func);
  9027. return func;
  9028. }
  9029. IHqlExpression * CHqlAlienType::queryStoreFunction()
  9030. {
  9031. return queryMemberFunc(storeId);
  9032. }
  9033. IHqlExpression * CHqlAlienType::queryFunction(IIdAtom * id)
  9034. {
  9035. OwnedHqlExpr func = lookupSymbol(id);
  9036. if (func)
  9037. assertex(func->getOperator() == no_funcdef);
  9038. return func;
  9039. }
  9040. IHqlExpression * CHqlAlienType::queryMemberFunc(IIdAtom * search)
  9041. {
  9042. OwnedHqlExpr func = lookupSymbol(search);
  9043. assertex(func);
  9044. assertex(func->getOperator() == no_funcdef);
  9045. return func;
  9046. }
  9047. IHqlExpression *CHqlAlienType::lookupSymbol(IIdAtom * searchName)
  9048. {
  9049. HqlDummyLookupContext ctx(NULL);
  9050. return scope->lookupSymbol(searchName, LSFpublic, ctx);
  9051. }
  9052. size32_t CHqlAlienType::getSize()
  9053. {
  9054. return physical->getSize();
  9055. //return getMaxSize(); // would this be better?, and should the value be cached?
  9056. }
  9057. /* in parm _scope: linked */
  9058. extern IHqlExpression *createAlienType(IIdAtom * _id, IHqlScope *_scope)
  9059. {
  9060. assertex(_scope);
  9061. return new CHqlAlienType(_id, _scope, NULL);
  9062. }
  9063. extern IHqlExpression *createAlienType(IIdAtom * id, IHqlScope * scope, HqlExprArray &newkids, IHqlExpression * funcdef)
  9064. {
  9065. assertex(scope);
  9066. // assertex(!funcdef); // I'm not sure what value this has...
  9067. IHqlExpression * ret = new CHqlAlienType(id, scope, funcdef);
  9068. ForEachItemIn(idx2, newkids)
  9069. ret->addOperand(&OLINK(newkids.item(idx2)));
  9070. return ret->closeExpr();
  9071. }
  9072. //==============================================================================================================
  9073. /* In parm: scope is linked */
  9074. CHqlEnumType::CHqlEnumType(ITypeInfo * _type, IHqlScope *_scope) : CHqlExpressionWithType(no_enum, _type)
  9075. {
  9076. scope = _scope;
  9077. IHqlExpression * scopeExpr = queryExpression(scope);
  9078. infoFlags |= (scopeExpr->getInfoFlags() & HEFalwaysInherit);
  9079. infoFlags2 |= (scopeExpr->getInfoFlags2() & HEF2alwaysInherit);
  9080. }
  9081. CHqlEnumType::~CHqlEnumType()
  9082. {
  9083. ::Release(scope);
  9084. }
  9085. bool CHqlEnumType::equals(const IHqlExpression &r) const
  9086. {
  9087. if (!CHqlExpression::equals(r))
  9088. return false;
  9089. return scopesEqual(scope, const_cast<IHqlExpression &>(r).queryScope());
  9090. }
  9091. void CHqlEnumType::sethash()
  9092. {
  9093. // Can't use base class as that includes type (== this) which would make it different every time
  9094. CHqlExpression::sethash();
  9095. IHqlExpression * scopeExpr = queryExpression(scope);
  9096. if (scopeExpr)
  9097. hashcode ^= scopeExpr->getHash();
  9098. }
  9099. IHqlExpression *CHqlEnumType::clone(HqlExprArray &newkids)
  9100. {
  9101. assertex(newkids.ordinality() == 0);
  9102. return LINK(this);
  9103. }
  9104. /* in parm _scope: linked */
  9105. extern IHqlExpression *createEnumType(ITypeInfo * _type, IHqlScope *_scope)
  9106. {
  9107. if (!_scope) _scope = createScope();
  9108. IHqlExpression * ret = new CHqlEnumType(_type, _scope);
  9109. return ret->closeExpr();
  9110. }
  9111. //==============================================================================================================
  9112. void CHqlTemplateFunctionContext::sethash()
  9113. {
  9114. CHqlExpression::sethash();
  9115. hashcode = hashc((unsigned char *) context, sizeof(context), hashcode);
  9116. }
  9117. //==============================================================================================================
  9118. extern IHqlExpression *createParameter(IIdAtom * id, unsigned idx, ITypeInfo *type, HqlExprArray & attrs)
  9119. {
  9120. return CHqlParameter::makeParameter(id, idx, type, attrs);
  9121. }
  9122. extern IHqlExpression *createValue(node_operator op)
  9123. {
  9124. return CHqlExpressionWithType::makeExpression(op, NULL, NULL);
  9125. }
  9126. extern IHqlExpression *createValue(node_operator op, ITypeInfo *type)
  9127. {
  9128. return CHqlExpressionWithType::makeExpression(op, type, NULL);
  9129. }
  9130. extern IHqlExpression *createOpenValue(node_operator op, ITypeInfo *type)
  9131. {
  9132. #if defined(_DEBUG)
  9133. //reports calling the wrong function if enabled.... some examples can't be fixed yet...
  9134. if (type)
  9135. {
  9136. switch (op)
  9137. {
  9138. case no_funcdef:
  9139. case no_translated:
  9140. break;
  9141. default:
  9142. switch(type->getTypeCode())
  9143. {
  9144. // MORE - is this right???
  9145. case type_groupedtable:
  9146. case type_table:
  9147. assertex(!"createDataset should be called instead");
  9148. }
  9149. }
  9150. }
  9151. #endif
  9152. return new CHqlExpressionWithType(op, type);
  9153. }
  9154. extern IHqlExpression *createOpenNamedValue(node_operator op, ITypeInfo *type, IIdAtom * id)
  9155. {
  9156. #if defined(_DEBUG)
  9157. //reports calling the wrong function if enabled.... some examples can't be fixed yet...
  9158. if (type)
  9159. {
  9160. switch (op)
  9161. {
  9162. case no_funcdef:
  9163. case no_translated:
  9164. break;
  9165. default:
  9166. switch(type->getTypeCode())
  9167. {
  9168. // MORE - is this right???
  9169. case type_groupedtable:
  9170. case type_table:
  9171. assertex(!"createDataset should be called instead");
  9172. }
  9173. }
  9174. }
  9175. #endif
  9176. return new CHqlNamedExpression(op, type, id, NULL);
  9177. }
  9178. extern IHqlExpression *createValue(node_operator op, IHqlExpression *p1, IHqlExpression *p2)
  9179. {
  9180. return CHqlExpressionWithType::makeExpression(op, p1->getType(), p1, p2, NULL);
  9181. }
  9182. extern IHqlExpression *createValue(node_operator op, ITypeInfo *type, IHqlExpression *p1)
  9183. {
  9184. return CHqlExpressionWithType::makeExpression(op, type, p1, NULL);
  9185. }
  9186. extern IHqlExpression *createValue(node_operator op, ITypeInfo *type, IHqlExpression *p1, IHqlExpression *p2)
  9187. {
  9188. return CHqlExpressionWithType::makeExpression(op, type, p1, p2, NULL);
  9189. }
  9190. extern IHqlExpression *createValue(node_operator op, ITypeInfo *type, IHqlExpression *p1, IHqlExpression *p2, IHqlExpression *p3)
  9191. {
  9192. return CHqlExpressionWithType::makeExpression(op, type, p1, p2, p3, NULL);
  9193. }
  9194. extern IHqlExpression *createValue(node_operator op, ITypeInfo *type, IHqlExpression *p1, IHqlExpression *p2, IHqlExpression *p3, IHqlExpression *p4)
  9195. {
  9196. return CHqlExpressionWithType::makeExpression(op, type, p1, p2, p3, p4, NULL);
  9197. }
  9198. extern IHqlExpression *createValueF(node_operator op, ITypeInfo *type, ...)
  9199. {
  9200. HqlExprArray children;
  9201. va_list args;
  9202. va_start(args, type);
  9203. for (;;)
  9204. {
  9205. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  9206. if (!parm)
  9207. break;
  9208. #ifdef _DEBUG
  9209. assertex(QUERYINTERFACE(parm, IHqlExpression));
  9210. #endif
  9211. if (parm->getOperator() == no_comma)
  9212. {
  9213. parm->unwindList(children, no_comma);
  9214. parm->Release();
  9215. }
  9216. else
  9217. children.append(*parm);
  9218. }
  9219. va_end(args);
  9220. return CHqlExpressionWithType::makeExpression(op, type, children);
  9221. }
  9222. extern HQL_API IHqlExpression *createValue(node_operator op, ITypeInfo * type, unsigned num, IHqlExpression * * args)
  9223. {
  9224. IHqlExpression * expr = createOpenValue(op, type);
  9225. unsigned index;
  9226. for (index = 0; index < num; index++)
  9227. expr->addOperand(args[index]);
  9228. return expr->closeExpr();
  9229. }
  9230. extern HQL_API IHqlExpression * createValueFromCommaList(node_operator op, ITypeInfo * type, IHqlExpression * argsExpr)
  9231. {
  9232. HqlExprArray args;
  9233. if (argsExpr)
  9234. {
  9235. argsExpr->unwindList(args, no_comma);
  9236. argsExpr->Release();
  9237. }
  9238. return createValue(op, type, args);
  9239. }
  9240. extern HQL_API IHqlExpression * createValueSafe(node_operator op, ITypeInfo * type, const HqlExprArray & args)
  9241. {
  9242. ForEachItemIn(idx, args)
  9243. args.item(idx).Link();
  9244. HqlExprArray & castArgs = const_cast<HqlExprArray &>(args);
  9245. IHqlExpression * * exprList = static_cast<IHqlExpression * *>(castArgs.getArray());
  9246. return createValue(op, type, args.ordinality(), exprList);
  9247. }
  9248. extern HQL_API IHqlExpression * createValueSafe(node_operator op, ITypeInfo * type, const HqlExprArray & args, unsigned from, unsigned max)
  9249. {
  9250. assertex(from <= args.ordinality() && max <= args.ordinality() && from <= max);
  9251. for (unsigned idx=from; idx < max; idx++)
  9252. args.item(idx).Link();
  9253. HqlExprArray & castArgs = const_cast<HqlExprArray &>(args);
  9254. IHqlExpression * * exprList = static_cast<IHqlExpression * *>(castArgs.getArray());
  9255. return createValue(op, type, max-from, exprList + from);
  9256. }
  9257. extern IHqlExpression *createBoolExpr(node_operator op, IHqlExpression *p1)
  9258. {
  9259. return CHqlExpressionWithType::makeExpression(op, makeBoolType(), p1, NULL);
  9260. }
  9261. extern IHqlExpression *createBoolExpr(node_operator op, IHqlExpression *p1, IHqlExpression *p2)
  9262. {
  9263. return CHqlExpressionWithType::makeExpression(op, makeBoolType(), p1, p2, NULL);
  9264. }
  9265. extern IHqlExpression *createBoolExpr(node_operator op, IHqlExpression *p1, IHqlExpression *p2, IHqlExpression *p3)
  9266. {
  9267. return CHqlExpressionWithType::makeExpression(op, makeBoolType(), p1, p2, p3, NULL);
  9268. }
  9269. extern IHqlExpression *createField(IIdAtom *id, ITypeInfo *type, HqlExprArray & _ownedOperands)
  9270. {
  9271. IHqlExpression * field = new CHqlField(id, type, _ownedOperands);
  9272. return field->closeExpr();
  9273. }
  9274. extern IHqlExpression *createField(IIdAtom *id, ITypeInfo *type, IHqlExpression *defaultValue, IHqlExpression * attrs)
  9275. {
  9276. HqlExprArray args;
  9277. if (defaultValue)
  9278. args.append(*defaultValue);
  9279. if (attrs)
  9280. {
  9281. attrs->unwindList(args, no_comma);
  9282. attrs->Release();
  9283. }
  9284. IHqlExpression* expr = new CHqlField(id, type, args);
  9285. return expr->closeExpr();
  9286. }
  9287. extern HQL_API IHqlExpression *createQuoted(const char * text, ITypeInfo *type)
  9288. {
  9289. return CHqlVariable::makeVariable(no_quoted, text, type);
  9290. }
  9291. extern HQL_API IHqlExpression *createVariable(const char * name, ITypeInfo *type)
  9292. {
  9293. return CHqlVariable::makeVariable(no_variable, name, type);
  9294. }
  9295. IHqlExpression *createAttribute(node_operator op, IAtom * name, IHqlExpression * value, IHqlExpression *value2, IHqlExpression * value3)
  9296. {
  9297. assertex(name);
  9298. IHqlExpression * ret = CHqlAttribute::makeAttribute(op, name);
  9299. if (value)
  9300. {
  9301. ret->addOperand(value);
  9302. if (value2)
  9303. ret->addOperand(value2);
  9304. if (value3)
  9305. ret->addOperand(value3);
  9306. }
  9307. return ret->closeExpr();
  9308. }
  9309. IHqlExpression *createAttribute(node_operator op, IAtom * name, HqlExprArray & args)
  9310. {
  9311. IHqlExpression * ret = CHqlAttribute::makeAttribute(op, name);
  9312. ForEachItemIn(idx, args)
  9313. ret->addOperand(&OLINK(args.item(idx)));
  9314. return ret->closeExpr();
  9315. }
  9316. extern HQL_API IHqlExpression *createAttribute(IAtom * name, IHqlExpression * value, IHqlExpression *value2, IHqlExpression * value3)
  9317. {
  9318. return createAttribute(no_attr, name, value, value2, value3);
  9319. }
  9320. extern HQL_API IHqlExpression *createAttribute(IAtom * name, HqlExprArray & args)
  9321. {
  9322. return createAttribute(no_attr, name, args);
  9323. }
  9324. extern HQL_API IHqlExpression *createExprAttribute(IAtom * name, IHqlExpression * value, IHqlExpression *value2, IHqlExpression * value3)
  9325. {
  9326. return createAttribute(no_attr_expr, name, value, value2, value3);
  9327. }
  9328. extern HQL_API IHqlExpression *createExprAttribute(IAtom * name, HqlExprArray & args)
  9329. {
  9330. return createAttribute(no_attr_expr, name, args);
  9331. }
  9332. extern HQL_API IHqlExpression *createLinkAttribute(IAtom * name, IHqlExpression * value, IHqlExpression *value2, IHqlExpression * value3)
  9333. {
  9334. return createAttribute(no_attr_link, name, value, value2, value3);
  9335. }
  9336. extern HQL_API IHqlExpression *createLinkAttribute(IAtom * name, HqlExprArray & args)
  9337. {
  9338. return createAttribute(no_attr_link, name, args);
  9339. }
  9340. extern HQL_API IHqlExpression *createUnknown(node_operator op, ITypeInfo * type, IAtom * name, IInterface * extra)
  9341. {
  9342. IHqlExpression * ret = CHqlUnknown::makeUnknown(op, type, name, extra);
  9343. return ret->closeExpr();
  9344. }
  9345. extern HQL_API IHqlExpression *createSequence(node_operator op, ITypeInfo * type, IAtom * name, unsigned __int64 seq)
  9346. {
  9347. IHqlExpression * ret = CHqlSequence::makeSequence(op, type, name, seq);
  9348. return ret->closeExpr();
  9349. }
  9350. IHqlExpression *createSymbol(IIdAtom * id, IHqlExpression *expr, unsigned exportFlags)
  9351. {
  9352. return CHqlSimpleSymbol::makeSymbol(id, NULL, expr, NULL, exportFlags);
  9353. }
  9354. IHqlExpression * createSymbol(IIdAtom * id, IIdAtom * moduleName, IHqlExpression * expr, bool exported, bool shared, unsigned symbolFlags)
  9355. {
  9356. return CHqlSimpleSymbol::makeSymbol(id, moduleName, expr, NULL, combineSymbolFlags(symbolFlags, exported, shared));
  9357. }
  9358. IHqlExpression * createSymbol(IIdAtom * _id, IIdAtom * moduleName, IHqlExpression *expr, IHqlExpression * funcdef,
  9359. bool exported, bool shared, unsigned symbolFlags,
  9360. IFileContents *fc, int lineno, int column,
  9361. int _startpos, int _bodypos, int _endpos)
  9362. {
  9363. return CHqlNamedSymbol::makeSymbol(_id, moduleName, expr, funcdef,
  9364. exported, shared, symbolFlags,
  9365. fc, lineno, column, _startpos, _bodypos, _endpos);
  9366. }
  9367. IHqlExpression *createDataset(node_operator op, IHqlExpression *dataset, IHqlExpression *list)
  9368. {
  9369. HqlExprArray parms;
  9370. parms.append(*dataset);
  9371. if (list)
  9372. {
  9373. list->unwindList(parms, no_comma);
  9374. list->Release();
  9375. }
  9376. return createDataset(op, parms);
  9377. }
  9378. IHqlExpression *createDataset(node_operator op, IHqlExpression *dataset)
  9379. {
  9380. HqlExprArray parms;
  9381. parms.append(*dataset);
  9382. return createDataset(op, parms);
  9383. }
  9384. extern IHqlExpression *createDatasetF(node_operator op, ...)
  9385. {
  9386. HqlExprArray children;
  9387. va_list args;
  9388. va_start(args, op);
  9389. for (;;)
  9390. {
  9391. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  9392. if (!parm)
  9393. break;
  9394. #ifdef _DEBUG
  9395. assertex(QUERYINTERFACE(parm, IHqlExpression));
  9396. #endif
  9397. if (parm->getOperator() == no_comma)
  9398. {
  9399. parm->unwindList(children, no_comma);
  9400. parm->Release();
  9401. }
  9402. else
  9403. children.append(*parm);
  9404. }
  9405. va_end(args);
  9406. return createDataset(op, children);
  9407. }
  9408. IHqlExpression *createDictionary(node_operator op, HqlExprArray & parms)
  9409. {
  9410. #ifdef GATHER_LINK_STATS
  9411. insideCreate++;
  9412. #endif
  9413. Owned<ITypeInfo> type = NULL;
  9414. switch (op)
  9415. {
  9416. case no_createdictionary:
  9417. type.setown(makeDictionaryType(makeRowType(createRecordType(&parms.item(0)))));
  9418. break;
  9419. case no_select:
  9420. case no_mapto:
  9421. type.set(parms.item(1).queryType());
  9422. break;
  9423. case no_addfiles:
  9424. type.set(parms.item(0).queryType()); // It's an error if they don't all match, caught elsewhere (?)
  9425. break;
  9426. case no_if:
  9427. type.set(parms.item(1).queryType()); // It's an error if they don't match, caught elsewhere
  9428. break;
  9429. case no_chooseds:
  9430. type.set(parms.item(1).queryType()); // It's an error if they don't match, caught elsewhere
  9431. break;
  9432. case no_case:
  9433. //following is wrong, but they get removed pretty quickly so I don't really care
  9434. type.set(parms.item(1).queryType());
  9435. break;
  9436. case no_map:
  9437. //following is wrong, but they get removed pretty quickly so I don't really care
  9438. type.set(parms.item(0).queryType());
  9439. break;
  9440. case no_null:
  9441. case no_fail:
  9442. case no_anon:
  9443. case no_workunit_dataset:
  9444. case no_getgraphresult:
  9445. case no_getresult:
  9446. {
  9447. IHqlExpression * record = &parms.item(0);
  9448. IHqlExpression * metadata = queryAttribute(_metadata_Atom, parms);
  9449. bool linkCounted = (queryAttribute(_linkCounted_Atom, parms) || recordRequiresLinkCount(record));
  9450. if (!metadata)
  9451. {
  9452. ITypeInfo * recordType = createRecordType(record);
  9453. assertex(recordType->getTypeCode() == type_record);
  9454. ITypeInfo * rowType = makeRowType(recordType);
  9455. type.setown(makeDictionaryType(rowType));
  9456. }
  9457. else
  9458. UNIMPLEMENTED_XY("Type calculation for dictionary operator", getOpString(op));
  9459. if (linkCounted)
  9460. type.setown(setLinkCountedAttr(type, true));
  9461. break;
  9462. }
  9463. case no_serialize:
  9464. {
  9465. assertex(parms.ordinality() >= 2);
  9466. IHqlExpression & form = parms.item(1);
  9467. assertex(form.isAttribute());
  9468. assertex(form.queryName() != diskAtom); //It should be a dataset instead...
  9469. type.setown(getSerializedForm(parms.item(0).queryType(), form.queryName()));
  9470. break;
  9471. }
  9472. case no_deserialize:
  9473. {
  9474. assertex(parms.ordinality() >= 3);
  9475. IHqlExpression & record = parms.item(1);
  9476. IHqlExpression & form = parms.item(2);
  9477. assertex(form.isAttribute());
  9478. ITypeInfo * recordType = record.queryType();
  9479. OwnedITypeInfo rowType = makeRowType(LINK(recordType));
  9480. assertex(record.getOperator() == no_record);
  9481. type.setown(makeDictionaryType(LINK(rowType)));
  9482. type.setown(setLinkCountedAttr(type, true));
  9483. #ifdef _DEBUG
  9484. OwnedITypeInfo serializedType = getSerializedForm(type, form.queryName());
  9485. assertex(recordTypesMatch(serializedType, parms.item(0).queryType()));
  9486. #endif
  9487. break;
  9488. }
  9489. case no_nofold:
  9490. case no_nohoist:
  9491. case no_thor:
  9492. case no_nothor:
  9493. case no_alias:
  9494. case no_translated:
  9495. case no_catch:
  9496. case no_colon:
  9497. case no_globalscope:
  9498. case no_thisnode:
  9499. type.set(parms.item(0).queryType());
  9500. break;
  9501. default:
  9502. UNIMPLEMENTED_XY("Type calculation for dictionary operator", getOpString(op));
  9503. break;
  9504. }
  9505. IHqlExpression * ret = CHqlDictionary::makeDictionary(op, type.getClear(), parms);
  9506. #ifdef GATHER_LINK_STATS
  9507. insideCreate--;
  9508. #endif
  9509. return ret;
  9510. }
  9511. IHqlExpression *createDictionary(node_operator op, IHqlExpression *dictionary, IHqlExpression *list)
  9512. {
  9513. HqlExprArray parms;
  9514. parms.append(*dictionary);
  9515. if (list)
  9516. {
  9517. list->unwindList(parms, no_comma);
  9518. list->Release();
  9519. }
  9520. return createDictionary(op, parms);
  9521. }
  9522. IHqlExpression *createDictionary(node_operator op, IHqlExpression *dictionary)
  9523. {
  9524. HqlExprArray parms;
  9525. parms.append(*dictionary);
  9526. return createDictionary(op, parms);
  9527. }
  9528. IHqlExpression * createAliasOwn(IHqlExpression * expr, IHqlExpression * attr)
  9529. {
  9530. if (expr->getOperator() == no_alias)
  9531. return expr;
  9532. if (expr->isDataset())
  9533. return createDataset(no_alias, expr, attr);
  9534. if (expr->isDatarow())
  9535. return createRow(no_alias, expr, attr);
  9536. return createValueF(no_alias, expr->getType(), expr, attr, NULL); // unwinds no_comma
  9537. }
  9538. IHqlExpression * createTypedValue(node_operator op, ITypeInfo * type, HqlExprArray & args)
  9539. {
  9540. switch (type->getTypeCode())
  9541. {
  9542. case type_groupedtable:
  9543. case type_table:
  9544. return createDataset(op, args);
  9545. case type_dictionary:
  9546. return createDictionary(op, args);
  9547. case type_row:
  9548. return createRow(op, args);
  9549. default:
  9550. return createValue(op, LINK(type), args);
  9551. }
  9552. }
  9553. //---------------------------------------------------------------------------
  9554. /*
  9555. Calls and parameter binding.
  9556. This has various complications including:
  9557. * Expanding nested attributes.
  9558. * Delayed expansion of calls passed in as parameters.
  9559. * Interfaces which ensure all instances have the same prototype.
  9560. Originally this was done so that the function call was inlined as soon as the call was encountered.
  9561. - Ensure all parameters in nested definitions have unique expressions so parent parameters aren't
  9562. substituted with child parameters.
  9563. Now it is done as follows:
  9564. - When a call is created a no_call node is created (or no_externalcall/no_libraryscopeinstance)
  9565. - Later the tree of calls is expanded.
  9566. - It is impossible to guarantee that all parameters in the expression tree are unique (because of interfaces if nothing else)
  9567. so can't use a single transform.
  9568. => Transform a call at a time
  9569. => After a call is transformed have an option to transform the body in a nested transform.
  9570. */
  9571. bool isExternalFunction(IHqlExpression * funcdef)
  9572. {
  9573. if (funcdef->getOperator() == no_funcdef)
  9574. {
  9575. IHqlExpression * body = funcdef->queryChild(0);
  9576. return (body->getOperator() == no_external);
  9577. }
  9578. return false;
  9579. }
  9580. bool isEmbedFunction(IHqlExpression * funcdef)
  9581. {
  9582. IHqlExpression * body = funcdef->queryChild(0);
  9583. if (body->getOperator() != no_outofline)
  9584. return false;
  9585. return body->queryChild(0)->getOperator() == no_embedbody;
  9586. }
  9587. bool isEmbedCall(IHqlExpression * expr)
  9588. {
  9589. assertex(expr->getOperator() == no_call);
  9590. return isEmbedFunction(expr->queryBody()->queryFunctionDefinition());
  9591. }
  9592. inline bool isExternalMethodDefinition(IHqlExpression * funcdef)
  9593. {
  9594. if (funcdef->getOperator() == no_funcdef)
  9595. {
  9596. IHqlExpression * body = funcdef->queryChild(0);
  9597. if ((body->getOperator() == no_external) &&
  9598. (body->hasAttribute(methodAtom) || body->hasAttribute(omethodAtom)))
  9599. return true;
  9600. }
  9601. return false;
  9602. }
  9603. inline IHqlExpression * createCallExpression(IHqlExpression * funcdef, HqlExprArray & resolvedActuals)
  9604. {
  9605. IHqlExpression * body = funcdef->queryBody(true);
  9606. if (funcdef != body)
  9607. {
  9608. if (funcdef->getAnnotationKind() != annotate_symbol)
  9609. {
  9610. OwnedHqlExpr call = createCallExpression(body, resolvedActuals);
  9611. return funcdef->cloneAnnotation(call);
  9612. }
  9613. //Slightly nasty - need to save the parameters away because create may kill them
  9614. HqlExprArray clonedActuals;
  9615. appendArray(clonedActuals, resolvedActuals);
  9616. OwnedHqlExpr call = createCallExpression(body, resolvedActuals);
  9617. //Don't bother adding symbols for calls to external functions
  9618. if (call->getOperator() == no_externalcall)
  9619. return LINK(call);
  9620. IHqlNamedAnnotation * annotation = static_cast<IHqlNamedAnnotation *>(funcdef->queryAnnotation());
  9621. return annotation->cloneSymbol(NULL, call, funcdef, &clonedActuals);
  9622. }
  9623. if (funcdef->getOperator() == no_funcdef)
  9624. {
  9625. IHqlExpression * funcBody = funcdef->queryChild(0);
  9626. switch (funcBody->getOperator())
  9627. {
  9628. case no_external:
  9629. return CHqlExternalCall::makeExternalCall(LINK(funcdef), funcBody->getType(), resolvedActuals);
  9630. case no_libraryscope:
  9631. return createLibraryInstance(LINK(funcdef), resolvedActuals);
  9632. }
  9633. }
  9634. return CHqlDelayedCall::makeDelayedCall(LINK(funcdef), resolvedActuals);
  9635. }
  9636. struct CallExpansionContext
  9637. {
  9638. CallExpansionContext()
  9639. {
  9640. errors = NULL;
  9641. functionCache = NULL;
  9642. expandNestedCalls = true;
  9643. forceOutOfLineExpansion = false;
  9644. }
  9645. inline bool expandFunction(IHqlExpression * funcdef)
  9646. {
  9647. if (funcdef->getOperator() == no_funcdef)
  9648. {
  9649. //A no_funcdef means we either have an outofline function, or we can expand the body
  9650. IHqlExpression * body = funcdef->queryChild(0);
  9651. switch (body->getOperator())
  9652. {
  9653. case no_outofline:
  9654. return forceOutOfLineExpansion;
  9655. }
  9656. return true;
  9657. }
  9658. return false;
  9659. }
  9660. inline bool expandFunctionCall(IHqlExpression * call)
  9661. {
  9662. return expandFunction(call->queryBody()->queryFunctionDefinition());
  9663. }
  9664. IErrorReceiver * errors;
  9665. HqlExprArray * functionCache;
  9666. bool expandNestedCalls;
  9667. bool forceOutOfLineExpansion;
  9668. };
  9669. extern IHqlExpression * expandFunctionCall(CallExpansionContext & ctx, IHqlExpression * call);
  9670. static HqlTransformerInfo parameterBindTransformerInfo("ParameterBindTransformer");
  9671. class ParameterBindTransformer : public QuickHqlTransformer
  9672. {
  9673. public:
  9674. ParameterBindTransformer(CallExpansionContext & _ctx)
  9675. : QuickHqlTransformer(parameterBindTransformerInfo, _ctx.errors),
  9676. ctx(_ctx)
  9677. {
  9678. }
  9679. IHqlExpression * createExpandedCall(IHqlExpression * call);
  9680. IHqlExpression * createBound(IHqlExpression *func, const HqlExprArray &actuals);
  9681. protected:
  9682. virtual IHqlExpression * createTransformed(IHqlExpression * expr)
  9683. {
  9684. //MORE: This test needs to be extended?
  9685. if (expr->isFullyBound() && !containsCall(expr, ctx.forceOutOfLineExpansion))
  9686. return LINK(expr);
  9687. return QuickHqlTransformer::createTransformed(expr);
  9688. }
  9689. virtual IHqlExpression * createTransformedBody(IHqlExpression * expr)
  9690. {
  9691. node_operator op = expr->getOperator();
  9692. //Parameters are being used a lot to select between two items in inside a function/module
  9693. //so much better if we trim the tree earlier....
  9694. switch (op)
  9695. {
  9696. case no_if:
  9697. {
  9698. IHqlExpression * cond = expr->queryChild(0);
  9699. OwnedHqlExpr newcond = transform(cond);
  9700. if (newcond->isConstant())
  9701. newcond.setown(foldHqlExpression(newcond));
  9702. IValue * value = newcond->queryValue();
  9703. if (value && !expr->isAction())
  9704. {
  9705. unsigned branch = value->getBoolValue() ? 1 : 2;
  9706. IHqlExpression * arg = expr->queryChild(branch);
  9707. if (arg)
  9708. return transform(arg);
  9709. }
  9710. break;
  9711. }
  9712. case no_map:
  9713. {
  9714. //This could strip leading failing matches, but for the moment only do that if we know
  9715. //which branch matches.
  9716. ForEachChild(i, expr)
  9717. {
  9718. IHqlExpression * cur = expr->queryChild(i);
  9719. if (cur->getOperator() == no_mapto)
  9720. {
  9721. OwnedHqlExpr newcond = transform(cur->queryChild(0));
  9722. if (newcond->isConstant())
  9723. newcond.setown(foldHqlExpression(newcond));
  9724. IValue * value = newcond->queryValue();
  9725. if (!value)
  9726. break;
  9727. if (value->getBoolValue())
  9728. return transform(cur->queryChild(1));
  9729. }
  9730. else if (!cur->isAttribute())
  9731. return transform(cur);
  9732. }
  9733. break;
  9734. }
  9735. case no_case:
  9736. {
  9737. IHqlExpression * search = expr->queryChild(0);
  9738. if (!search->isConstant())
  9739. break;
  9740. OwnedHqlExpr folded = foldHqlExpression(search);
  9741. IValue * searchValue = folded->queryValue();
  9742. if (!searchValue)
  9743. break;
  9744. ITypeInfo * searchType = searchValue->queryType();
  9745. ForEachChildFrom(i, expr, 1)
  9746. {
  9747. IHqlExpression * cur = expr->queryChild(i);
  9748. if (cur->getOperator() == no_mapto)
  9749. {
  9750. OwnedHqlExpr newcond = transform(cur->queryChild(0));
  9751. if (newcond->isConstant())
  9752. newcond.setown(foldHqlExpression(newcond));
  9753. IValue * compareValue = newcond->queryValue();
  9754. if (!compareValue)
  9755. break;
  9756. if (searchType != newcond->queryType())
  9757. {
  9758. Owned<ITypeInfo> type = ::getPromotedECLCompareType(searchType, newcond->queryType());
  9759. OwnedHqlExpr castSearch = ensureExprType(folded, type);
  9760. OwnedHqlExpr castCompare = ensureExprType(newcond, type);
  9761. IValue * castSearchValue = castSearch->queryValue();
  9762. IValue * castCompareValue = castCompare->queryValue();
  9763. if (!castSearchValue || !castCompareValue)
  9764. break;
  9765. if (castSearchValue->compare(castCompareValue) == 0)
  9766. return transform(cur->queryChild(1));
  9767. }
  9768. else
  9769. {
  9770. if (searchValue->compare(compareValue) == 0)
  9771. return transform(cur->queryChild(1));
  9772. }
  9773. }
  9774. else if (!cur->isAttribute())
  9775. return transform(cur);
  9776. }
  9777. break;
  9778. }
  9779. case no_delayedselect:
  9780. {
  9781. IHqlExpression * oldModule = expr->queryChild(1);
  9782. OwnedHqlExpr newModule = transform(oldModule);
  9783. if (oldModule != newModule)
  9784. {
  9785. IIdAtom * selectedName = expr->queryChild(3)->queryId();
  9786. newModule.setown(checkCreateConcreteModule(ctx.errors, newModule, newModule->queryAttribute(_location_Atom)));
  9787. HqlDummyLookupContext dummyctx(ctx.errors);
  9788. IHqlScope * newScope = newModule->queryScope();
  9789. if (newScope)
  9790. return newScope->lookupSymbol(selectedName, makeLookupFlags(true, expr->hasAttribute(ignoreBaseAtom), false), dummyctx);
  9791. return ::replaceChild(expr, 1, newModule);
  9792. }
  9793. break;
  9794. }
  9795. }
  9796. OwnedHqlExpr transformed = QuickHqlTransformer::createTransformedBody(expr);
  9797. if ((op == no_call) && ctx.expandNestedCalls)
  9798. {
  9799. if (ctx.expandFunctionCall(transformed))
  9800. return expandFunctionCall(ctx, transformed);
  9801. }
  9802. return transformed.getClear();
  9803. }
  9804. protected:
  9805. IHqlExpression * createBoundBody(IHqlExpression *func, const HqlExprArray &actuals);
  9806. IHqlExpression * createExpandedCall(IHqlExpression *funcdef, const HqlExprArray & resolvedActuals);
  9807. protected:
  9808. CallExpansionContext & ctx;
  9809. };
  9810. IHqlExpression * ParameterBindTransformer::createBoundBody(IHqlExpression *funcdef, const HqlExprArray &actuals)
  9811. {
  9812. //The following can be created from (undocumented) conditional statements, and possibly conditional modules once implemented
  9813. //As far as I know these conditional items can only be present the first time a function is bound.
  9814. node_operator op = funcdef->getOperator();
  9815. switch (op)
  9816. {
  9817. case no_if:
  9818. {
  9819. IHqlExpression * cond = funcdef->queryChild(0);
  9820. OwnedHqlExpr left = createBoundBody(funcdef->queryChild(1), actuals);
  9821. OwnedHqlExpr right = createBoundBody(funcdef->queryChild(2), actuals);
  9822. return createIf(LINK(cond), left.getClear(), right.getClear());
  9823. }
  9824. case no_mapto:
  9825. {
  9826. OwnedHqlExpr mapped = createBoundBody(funcdef->queryChild(1), actuals);
  9827. return createValue(no_mapto, mapped->getType(), LINK(funcdef->queryChild(0)), LINK(mapped));
  9828. }
  9829. case no_map:
  9830. {
  9831. HqlExprArray args;
  9832. ForEachChild(i, funcdef)
  9833. args.append(*createBoundBody(funcdef->queryChild(i), actuals));
  9834. return createTypedValue(no_map, args.item(0).queryType(), args);
  9835. }
  9836. }
  9837. OwnedHqlExpr newFuncdef;
  9838. if (op == no_funcdef)
  9839. {
  9840. //A no_funcdef means we either have an outofline function, or we can expand the body
  9841. IHqlExpression * body = funcdef->queryChild(0);
  9842. switch (body->getOperator())
  9843. {
  9844. case no_outofline:
  9845. {
  9846. if (ctx.forceOutOfLineExpansion)
  9847. return transform(body->queryChild(0));
  9848. HqlExprArray args;
  9849. args.append(*LINK(body));
  9850. args.append(*LINK(funcdef->queryChild(1)));
  9851. newFuncdef.setown(completeTransform(funcdef, args));
  9852. break;
  9853. }
  9854. default:
  9855. return transform(body);
  9856. }
  9857. }
  9858. else
  9859. newFuncdef.setown(transform(funcdef));
  9860. HqlExprArray clonedActuals;
  9861. appendArray(clonedActuals, actuals);
  9862. return createCallExpression(newFuncdef, clonedActuals);
  9863. }
  9864. IHqlExpression * ParameterBindTransformer::createExpandedCall(IHqlExpression * call)
  9865. {
  9866. HqlExprArray actuals;
  9867. unwindChildren(actuals, call);
  9868. while (actuals.ordinality() && actuals.tos().isAttribute())
  9869. actuals.pop();
  9870. return createExpandedCall(call->queryBody()->queryFunctionDefinition(), actuals);
  9871. }
  9872. IHqlExpression * ParameterBindTransformer::createExpandedCall(IHqlExpression *funcdef, const HqlExprArray & resolvedActuals)
  9873. {
  9874. assertex(funcdef->getOperator() == no_funcdef);
  9875. IHqlExpression * formals = funcdef->queryChild(1);
  9876. assertex(formals->numChildren() == resolvedActuals.length());
  9877. ForEachItemIn(i, resolvedActuals)
  9878. {
  9879. IHqlExpression * formal = formals->queryChild(i);
  9880. IHqlExpression * actual = &resolvedActuals.item(i);
  9881. formal->queryBody()->setTransformExtra(actual);
  9882. }
  9883. return createBoundBody(funcdef, resolvedActuals);
  9884. }
  9885. extern HQL_API bool isKey(IHqlExpression * expr)
  9886. {
  9887. switch (expr->getOperator())
  9888. {
  9889. case no_keyindex:
  9890. case no_newkeyindex:
  9891. return true;
  9892. case no_call:
  9893. {
  9894. IHqlExpression * funcdef = expr->queryBody()->queryFunctionDefinition();
  9895. if (funcdef->getOperator() == no_funcdef)
  9896. return isKey(funcdef->queryChild(0));
  9897. return false;
  9898. }
  9899. default:
  9900. return false;
  9901. }
  9902. }
  9903. //-------------------------------------------------------------------------------------
  9904. static HqlTransformerInfo callExpandTransformerInfo("CallExpandTransformer");
  9905. class CallExpandTransformer : public QuickHqlTransformer
  9906. {
  9907. public:
  9908. CallExpandTransformer(CallExpansionContext & _ctx)
  9909. : QuickHqlTransformer(callExpandTransformerInfo, _ctx.errors),
  9910. ctx(_ctx)
  9911. {
  9912. }
  9913. protected:
  9914. virtual IHqlExpression * createTransformedBody(IHqlExpression * expr)
  9915. {
  9916. if (!containsCall(expr, ctx.forceOutOfLineExpansion))
  9917. return LINK(expr);
  9918. OwnedHqlExpr transformed = QuickHqlTransformer::createTransformedBody(expr);
  9919. if (transformed->getOperator() == no_call)
  9920. {
  9921. IHqlExpression * funcdef = transformed->queryBody()->queryFunctionDefinition();
  9922. return queryExpandFunctionCall(funcdef, transformed);
  9923. }
  9924. return transformed.getClear();
  9925. }
  9926. IHqlExpression * queryExpandFunctionCall(IHqlExpression *funcdef, IHqlExpression * call)
  9927. {
  9928. //The following can be created from (undocumented) conditional statements, and possibly conditional modules once implemented
  9929. //As far as I know these conditional items can only be present the first time a function is bound.
  9930. node_operator op = funcdef->getOperator();
  9931. switch (op)
  9932. {
  9933. case no_if:
  9934. {
  9935. IHqlExpression * cond = funcdef->queryChild(0);
  9936. OwnedHqlExpr left = queryExpandFunctionCall(funcdef->queryChild(1), call);
  9937. OwnedHqlExpr right = queryExpandFunctionCall(funcdef->queryChild(2), call);
  9938. return createIf(LINK(cond), left.getClear(), right.getClear());
  9939. }
  9940. case no_mapto:
  9941. {
  9942. OwnedHqlExpr mapped = queryExpandFunctionCall(funcdef->queryChild(1), call);
  9943. return createValue(no_mapto, mapped->getType(), LINK(funcdef->queryChild(0)), LINK(mapped));
  9944. }
  9945. case no_map:
  9946. {
  9947. HqlExprArray args;
  9948. ForEachChild(i, funcdef)
  9949. args.append(*queryExpandFunctionCall(funcdef->queryChild(i), call));
  9950. return createTypedValue(no_map, args.item(0).queryType(), args);
  9951. }
  9952. }
  9953. IHqlExpression * oldFuncdef = call->queryBody()->queryFunctionDefinition();
  9954. OwnedHqlExpr newCall;
  9955. if (funcdef != oldFuncdef)
  9956. {
  9957. HqlExprArray actuals;
  9958. unwindChildren(actuals, call);
  9959. newCall.setown(createCallExpression(funcdef, actuals));
  9960. }
  9961. else
  9962. newCall.set(call);
  9963. if (ctx.expandFunction(funcdef))
  9964. return expandFunctionCall(ctx, newCall);
  9965. return newCall.getClear();
  9966. }
  9967. protected:
  9968. CallExpansionContext & ctx;
  9969. };
  9970. //-------------------------------------------------------------------------------------
  9971. static void createAssignAll(HqlExprArray & assigns, IHqlExpression * self, IHqlExpression * left, IHqlExpression * record)
  9972. {
  9973. ForEachChild(i, record)
  9974. {
  9975. IHqlExpression * cur = record->queryChild(i);
  9976. switch (cur->getOperator())
  9977. {
  9978. case no_record:
  9979. createAssignAll(assigns, self, left, cur);
  9980. break;
  9981. case no_ifblock:
  9982. createAssignAll(assigns, self, left, cur->queryChild(1));
  9983. break;
  9984. case no_field:
  9985. {
  9986. OwnedHqlExpr target = createSelectExpr(LINK(self), LINK(cur));
  9987. OwnedHqlExpr field = lookupNewSelectedField(left, cur);;
  9988. OwnedHqlExpr source = createSelectExpr(LINK(left), field.getClear());
  9989. assigns.append(*createAssign(target.getClear(), source.getClear()));
  9990. break;
  9991. }
  9992. }
  9993. }
  9994. }
  9995. static void normalizeCallParameters(HqlExprArray & resolvedActuals, IHqlExpression *funcdef, const HqlExprArray &actuals)
  9996. {
  9997. assertex(funcdef->isFunction());
  9998. //This is the root function called for binding a function.
  9999. //First associate each of the parameters with their values...
  10000. ITypeInfo * funcType = funcdef->queryType();
  10001. IHqlExpression * formals = queryFunctionParameters(funcType);
  10002. IHqlExpression * defaults = queryFunctionDefaults(funcdef);
  10003. unsigned maxFormal = formals->numChildren();
  10004. unsigned curActual = 0;
  10005. if (isExternalMethodDefinition(funcdef))
  10006. resolvedActuals.append(OLINK(actuals.item(curActual++)));
  10007. QuickExpressionReplacer defaultReplacer;
  10008. for (unsigned i = 0; i < maxFormal; i++)
  10009. {
  10010. //NOTE: For functional parameters, formal is a no_funcdef, not a no_param. I suspect something better should be implemented..
  10011. IHqlExpression * formal = formals->queryChild(i);
  10012. LinkedHqlExpr actual;
  10013. if (actuals.isItem(curActual))
  10014. actual.set(&actuals.item(curActual++));
  10015. if (!actual || actual->getOperator()==no_omitted || actual->isAttribute())
  10016. {
  10017. actual.set(queryDefaultValue(defaults, i));
  10018. if (!actual)
  10019. actual.setown(createNullExpr(formal));
  10020. else if (actual->getOperator() == no_sequence)
  10021. actual.setown(createSequenceExpr());
  10022. //implicit parameters added to out of line function definitions, may reference the function parameters (e..g, global(myParameter * 2)
  10023. //so they need substituting first. May also occur if defaults are based on other parameter values.
  10024. //MORE: Should probably lazily create the mapping etc since 95% of the time it won't be used
  10025. if (!actual->isFullyBound() && !actual->isFunction())
  10026. actual.setown(defaultReplacer.transform(actual));
  10027. }
  10028. ITypeInfo * type = formal->queryType();
  10029. if (type)
  10030. {
  10031. switch (type->getTypeCode())
  10032. {
  10033. case type_record:
  10034. // MORE - should be more exact? Don't add a cast when binding parameters into a transform...
  10035. break;
  10036. case type_table:
  10037. case type_groupedtable:
  10038. if (isAbstractDataset(formal))
  10039. {
  10040. #ifdef NEW_VIRTUAL_DATASETS
  10041. HqlExprArray abstractSelects;
  10042. gatherAbstractSelects(abstractSelects, funcdef->queryChild(0), formal);
  10043. if (actual->getOperator()==no_fieldmap)
  10044. {
  10045. LinkedHqlExpr map = actual->queryChild(1);
  10046. actual.set(actual->queryChild(0));
  10047. associateBindMap(abstractSelects, formal, actual, map);
  10048. }
  10049. associateBindByName(abstractSelects, formal, actual);
  10050. #else
  10051. if (actual->getOperator()==no_fieldmap)
  10052. actual.set(actual->queryChild(0));
  10053. #endif
  10054. }
  10055. else
  10056. {
  10057. OwnedHqlExpr actualRecord = getUnadornedRecordOrField(actual->queryRecord());
  10058. IHqlExpression * formalRecord = ::queryOriginalRecord(type);
  10059. OwnedHqlExpr normalFormalRecord = getUnadornedRecordOrField(formalRecord);
  10060. if (actualRecord && normalFormalRecord && normalFormalRecord->numChildren() && (normalFormalRecord->queryBody() != actualRecord->queryBody()))
  10061. {
  10062. //If the actual dataset is derived from the input dataset, then insert a project so types remain correct
  10063. //otherwise x+y will change meaning.
  10064. OwnedHqlExpr seqAttr = createSelectorSequence();
  10065. OwnedHqlExpr self = createSelector(no_self, formalRecord, NULL);
  10066. OwnedHqlExpr left = createSelector(no_left, actual, seqAttr);
  10067. HqlExprArray assigns;
  10068. createAssignAll(assigns, self, left, formalRecord);
  10069. OwnedHqlExpr transform = createValue(no_transform, makeTransformType(formalRecord->getType()), assigns);
  10070. actual.setown(createDataset(no_hqlproject, actual.getClear(), createComma(transform.getClear(), LINK(seqAttr))));
  10071. }
  10072. }
  10073. break;
  10074. case type_dictionary:
  10075. // MORE - needs some code
  10076. // For now, never cast
  10077. break;
  10078. case type_row:
  10079. case type_transform:
  10080. case type_function:
  10081. break;
  10082. case type_unicode:
  10083. if ((type->getSize() == UNKNOWN_LENGTH) && (actual->queryType()->getTypeCode() == type_varunicode))
  10084. break;
  10085. actual.setown(ensureExprType(actual, type));
  10086. break;
  10087. #if 0
  10088. case type_string:
  10089. if (type->getSize() == UNKNOWN_LENGTH)
  10090. {
  10091. ITypeInfo * actualType = actual->queryType();
  10092. if ((actualType->getTypeCode() == type_varstring) && (actualType->queryCharset() == type->queryCharset())))
  10093. break;
  10094. }
  10095. actual.setown(ensureExprType(actual, type));
  10096. break;
  10097. #endif
  10098. default:
  10099. if (type != actual->queryType())
  10100. actual.setown(ensureExprType(actual, type));
  10101. break;
  10102. }
  10103. }
  10104. defaultReplacer.setMapping(formal->queryBody(), actual);
  10105. resolvedActuals.append(*LINK(actual));
  10106. }
  10107. while (actuals.isItem(curActual))
  10108. {
  10109. IHqlExpression & actual = actuals.item(curActual++);
  10110. if (actual.isAttribute())
  10111. resolvedActuals.append(OLINK(actual));
  10112. }
  10113. }
  10114. static IHqlExpression * createNormalizedCall(IHqlExpression *funcdef, const HqlExprArray &actuals)
  10115. {
  10116. HqlExprArray resolvedActuals;
  10117. normalizeCallParameters(resolvedActuals, funcdef, actuals);
  10118. return createCallExpression(funcdef, resolvedActuals);
  10119. }
  10120. inline IHqlExpression * expandFunctionalCallBody(CallExpansionContext & ctx, IHqlExpression * call)
  10121. {
  10122. ParameterBindTransformer binder(ctx);
  10123. return binder.createExpandedCall(call);
  10124. }
  10125. static IHqlExpression * cachedExpandFunctionCallBody(CallExpansionContext & ctx, IHqlExpression * call)
  10126. {
  10127. if (ctx.functionCache)
  10128. {
  10129. CHqlCachedBoundFunction *cache2 = new CHqlCachedBoundFunction(call, ctx.forceOutOfLineExpansion);
  10130. Owned<CHqlCachedBoundFunction> cache = static_cast<CHqlCachedBoundFunction *>(cache2->closeExpr());
  10131. if (cache->bound)
  10132. return LINK(cache->bound);
  10133. IHqlExpression *ret = expandFunctionalCallBody(ctx, call);
  10134. cache->bound.set(ret);
  10135. ctx.functionCache->append(*cache.getClear());
  10136. return ret;
  10137. }
  10138. return expandFunctionalCallBody(ctx, call);
  10139. }
  10140. /* in parms: func NOT linked by caller */
  10141. static IHqlExpression * expandFunctionCallPreserveAnnotation(CallExpansionContext & ctx, IHqlExpression * call)
  10142. {
  10143. IHqlExpression * body = call->queryBody(true);
  10144. if (call == body)
  10145. {
  10146. if (call->getOperator() != no_call)
  10147. return LINK(call);
  10148. return cachedExpandFunctionCallBody(ctx, call);
  10149. }
  10150. OwnedHqlExpr bound = expandFunctionCallPreserveAnnotation(ctx, body);
  10151. //Strip symbol annotations from calls to external functions - since they just complicate the tree
  10152. //unnecessarily
  10153. if (call->getAnnotationKind() == annotate_symbol)
  10154. {
  10155. if (call->getOperator() == no_externalcall)
  10156. return LINK(bound);
  10157. }
  10158. if (bound == body)
  10159. return LINK(call);
  10160. return call->cloneAnnotation(bound);
  10161. }
  10162. extern IHqlExpression * createBoundFunction(IErrorReceiver * errors, IHqlExpression *func, HqlExprArray &actuals, HqlExprArray * functionCache, bool forceExpansion)
  10163. {
  10164. CallExpansionContext ctx;
  10165. ctx.errors = errors;
  10166. ctx.functionCache = functionCache;
  10167. OwnedHqlExpr call = createNormalizedCall(func, actuals);
  10168. if (func->getOperator() != no_funcdef)
  10169. return call.getClear();
  10170. if (!forceExpansion && canBeDelayed(func))
  10171. return call.getClear();
  10172. return expandFunctionCallPreserveAnnotation(ctx, call);
  10173. }
  10174. IHqlExpression * expandFunctionCall(CallExpansionContext & ctx, IHqlExpression * call)
  10175. {
  10176. return expandFunctionCallPreserveAnnotation(ctx, call);
  10177. }
  10178. IHqlExpression * expandOutOfLineFunctionCall(IHqlExpression * expr)
  10179. {
  10180. HqlExprArray functionCache;
  10181. CallExpansionContext ctx;
  10182. ctx.functionCache = &functionCache;
  10183. ctx.forceOutOfLineExpansion = true;
  10184. assertex(expr->getOperator() == no_call);
  10185. if (ctx.expandFunctionCall(expr))
  10186. return expandFunctionCallPreserveAnnotation(ctx, expr);
  10187. return LINK(expr);
  10188. }
  10189. void expandDelayedFunctionCalls(IErrorReceiver * errors, HqlExprArray & exprs)
  10190. {
  10191. HqlExprArray functionCache;
  10192. CallExpansionContext ctx;
  10193. ctx.functionCache = &functionCache;
  10194. ctx.errors = errors;
  10195. CallExpandTransformer binder(ctx);
  10196. HqlExprArray target;
  10197. binder.transformArray(exprs, target);
  10198. replaceArray(exprs, target);
  10199. }
  10200. extern IHqlExpression * createReboundFunction(IHqlExpression *func, HqlExprArray &actuals)
  10201. {
  10202. return createCallExpression(func, actuals);
  10203. }
  10204. //---------------------------------------------------------------------------------------------------------------
  10205. static void checkConsistent(IHqlExpression* e)
  10206. {
  10207. //Check there are no datasets in the expression other than no_activetable
  10208. if (!e) return;
  10209. OwnedHqlExpr e1 = replaceSelector(e, NULL, querySelfReference());
  10210. OwnedHqlExpr e2 = replaceSelector(e, queryActiveTableSelector(), querySelfReference());
  10211. if (e1 != e2)
  10212. {
  10213. DBGLOG("Paranoia: type information wasn't correctly normalized");
  10214. e1.setown(replaceSelector(e, NULL, querySelfReference()));
  10215. }
  10216. }
  10217. //NOTE: The type information - e.g., distribution, grouping, sorting cannot include the dataset of the primary file
  10218. //because for a no_newusertable etc. that would result in a circular reference.
  10219. //so all references to fields in the primary file have no_activetable as the selector.
  10220. IHqlExpression *createDataset(node_operator op, HqlExprArray & parms)
  10221. {
  10222. #ifdef GATHER_LINK_STATS
  10223. insideCreate++;
  10224. #endif
  10225. switch (op)
  10226. {
  10227. case no_select:
  10228. //This can occur in very unusual situations...
  10229. if ((parms.ordinality() > 2) && isAlwaysActiveRow(&parms.item(0)))
  10230. removeAttribute(parms, newAtom);
  10231. break;
  10232. case no_denormalize:
  10233. {
  10234. IHqlExpression * transform = &parms.item(3);
  10235. assertex(recordTypesMatch(parms.item(0).queryRecordType(), transform->queryRecordType()));
  10236. break;
  10237. }
  10238. case no_rollup:
  10239. {
  10240. IHqlExpression * transform = &parms.item(2);
  10241. assertRecordTypesMatch(parms.item(0).queryRecordType(), transform->queryRecordType());
  10242. break;
  10243. }
  10244. case no_iterate:
  10245. {
  10246. IHqlExpression * transform = &parms.item(1);
  10247. assertRecordTypesMatch(parms.item(0).queryRecordType(), transform->queryRecordType());
  10248. break;
  10249. }
  10250. }
  10251. #if 0
  10252. //Some debug code for adding a pseudo attribute to all datasets - to help find all places that wouldn't allow hints to
  10253. //be added without causing problems. no_filter, no_if, no_case, no_map still have issues.
  10254. if (!queryAttribute(_metadata_Atom, parms) &&
  10255. (op != no_select) && (op != no_translated) && (op != no_colon))
  10256. parms.append(*createAttribute(_metadata_Atom));
  10257. #endif
  10258. Owned<ITypeInfo> type = calculateDatasetType(op, parms);
  10259. IHqlExpression * ret = CHqlDataset::makeDataset(op, type.getClear(), parms);
  10260. #ifdef GATHER_LINK_STATS
  10261. insideCreate--;
  10262. #endif
  10263. return ret;
  10264. }
  10265. extern IHqlExpression *createNewDataset(IHqlExpression *name, IHqlExpression *recorddef, IHqlExpression *mode, IHqlExpression *parent, IHqlExpression *joinCondition, IHqlExpression * options)
  10266. {
  10267. HqlExprArray args;
  10268. args.append(*name);
  10269. if (recorddef)
  10270. args.append(*recorddef);
  10271. if (mode)
  10272. args.append(*mode);
  10273. if (parent)
  10274. args.append(*parent);
  10275. if (joinCondition)
  10276. args.append(*joinCondition);
  10277. if (options)
  10278. {
  10279. options->unwindList(args, no_comma);
  10280. options->Release();
  10281. }
  10282. return createDataset(no_table, args);
  10283. }
  10284. extern IHqlExpression *createRow(node_operator op, IHqlExpression *dataset, IHqlExpression *rowNum)
  10285. {
  10286. HqlExprArray args;
  10287. if (dataset)
  10288. args.append(*dataset);
  10289. if (rowNum)
  10290. {
  10291. rowNum->unwindList(args, no_comma);
  10292. rowNum->Release();
  10293. }
  10294. return createRow(op, args);
  10295. }
  10296. extern IHqlExpression *createRowF(node_operator op, ...)
  10297. {
  10298. HqlExprArray children;
  10299. va_list args;
  10300. va_start(args, op);
  10301. for (;;)
  10302. {
  10303. IHqlExpression *parm = va_arg(args, IHqlExpression *);
  10304. if (!parm)
  10305. break;
  10306. #ifdef _DEBUG
  10307. assertex(QUERYINTERFACE(parm, IHqlExpression));
  10308. #endif
  10309. if (parm->getOperator() == no_comma)
  10310. {
  10311. parm->unwindList(children, no_comma);
  10312. parm->Release();
  10313. }
  10314. else
  10315. children.append(*parm);
  10316. }
  10317. va_end(args);
  10318. return createRow(op, children);
  10319. }
  10320. extern IHqlExpression *createRow(node_operator op, HqlExprArray & args)
  10321. {
  10322. ITypeInfo * type = NULL;
  10323. switch (op)
  10324. {
  10325. case no_soapcall:
  10326. {
  10327. IHqlExpression & record = args.item(3);
  10328. type = makeRowType(record.getType());
  10329. break;
  10330. }
  10331. case no_soapcall_ds:
  10332. case no_newsoapcall:
  10333. {
  10334. IHqlExpression & record = args.item(4);
  10335. type = makeRowType(record.getType());
  10336. break;
  10337. }
  10338. case no_newsoapcall_ds:
  10339. {
  10340. IHqlExpression & record = args.item(5);
  10341. type = makeRowType(record.getType());
  10342. break;
  10343. }
  10344. case no_select:
  10345. {
  10346. IHqlExpression & field = args.item(1);
  10347. ITypeInfo * fieldType = field.queryType();
  10348. type_t fieldTC = fieldType->getTypeCode();
  10349. assertex(fieldTC == type_row);
  10350. type = LINK(fieldType);
  10351. break;
  10352. }
  10353. case no_embedbody:
  10354. case no_id2blob:
  10355. case no_temprow:
  10356. case no_projectrow: // arg(1) is actually a transform
  10357. {
  10358. IHqlExpression & record = args.item(1);
  10359. type = makeRowType(LINK(record.queryRecordType()));
  10360. if (queryAttribute(_linkCounted_Atom, args))
  10361. type = makeAttributeModifier(type, getLinkCountedAttr());
  10362. break;
  10363. }
  10364. case no_typetransfer:
  10365. case no_createrow:
  10366. case no_fromxml:
  10367. {
  10368. IHqlExpression & transform = args.item(0);
  10369. type = makeRowType(LINK(transform.queryRecordType()));
  10370. break;
  10371. }
  10372. case no_compound:
  10373. case no_case:
  10374. case no_mapto:
  10375. type = args.item(1).getType();
  10376. break;
  10377. case no_translated:
  10378. type = args.item(0).getType();
  10379. break;
  10380. case no_if:
  10381. type = args.item(1).getType();
  10382. //can be null if the
  10383. if (!type)
  10384. type = args.item(2).getType();
  10385. break;
  10386. case no_serialize:
  10387. {
  10388. assertex(args.ordinality() >= 2);
  10389. IHqlExpression & form = args.item(1);
  10390. assertex(form.isAttribute());
  10391. type = getSerializedForm(args.item(0).queryType(), form.queryName());
  10392. break;
  10393. }
  10394. case no_deserialize:
  10395. {
  10396. assertex(args.ordinality() >= 3);
  10397. IHqlExpression & record = args.item(1);
  10398. IHqlExpression & form = args.item(2);
  10399. assertex(form.isAttribute());
  10400. assertex(record.getOperator() == no_record);
  10401. ITypeInfo * recordType = record.queryType();
  10402. type = makeAttributeModifier(makeRowType(LINK(recordType)), getLinkCountedAttr());
  10403. #ifdef _DEBUG
  10404. OwnedITypeInfo serializedType = getSerializedForm(type, form.queryName());
  10405. ITypeInfo * childType = args.item(0).queryType();
  10406. assertex(recordTypesMatch(serializedType, childType));
  10407. #endif
  10408. break;
  10409. }
  10410. case no_getresult:
  10411. case no_getgraphresult:
  10412. {
  10413. IHqlExpression * record = &args.item(0);
  10414. type = makeRowType(record->getType());
  10415. if (recordRequiresLinkCount(record))
  10416. type = makeAttributeModifier(type, getLinkCountedAttr());
  10417. break;
  10418. }
  10419. case no_readspill:
  10420. {
  10421. IHqlExpression * record = queryOriginalRecord(&args.item(0));
  10422. type = makeRowType(record->getType());
  10423. if (recordRequiresLinkCount(record))
  10424. type = makeAttributeModifier(type, getLinkCountedAttr());
  10425. break;
  10426. }
  10427. default:
  10428. {
  10429. IHqlExpression * dataset = &args.item(0);
  10430. assertex(dataset);
  10431. ITypeInfo * datasetType = dataset->queryType();
  10432. if (datasetType)
  10433. {
  10434. if (datasetType->getTypeCode() == type_row)
  10435. type = LINK(datasetType);
  10436. else
  10437. type = makeRowType(LINK(dataset->queryRecordType()));
  10438. }
  10439. break;
  10440. }
  10441. }
  10442. if (!type)
  10443. type = makeRowType(NULL);
  10444. return CHqlRow::makeRow(op, type, args);
  10445. }
  10446. extern IHqlExpression *createList(node_operator op, ITypeInfo *type, IHqlExpression *list)
  10447. {
  10448. HqlExprArray parms;
  10449. if (list)
  10450. {
  10451. list->unwindList(parms, no_comma);
  10452. list->Release();
  10453. }
  10454. return CHqlExpressionWithType::makeExpression(op, type, parms);
  10455. }
  10456. extern IHqlExpression *createBinaryList(node_operator op, HqlExprArray & args)
  10457. {
  10458. unsigned numArgs = args.ordinality();
  10459. assertex(numArgs != 0);
  10460. IHqlExpression * ret = &OLINK(args.item(0));
  10461. for (unsigned idx = 1; idx < numArgs; idx++)
  10462. ret = createValue(op, ret->getType(), ret, &OLINK(args.item(idx)));
  10463. return ret;
  10464. }
  10465. extern IHqlExpression *createLeftBinaryList(node_operator op, HqlExprArray & args)
  10466. {
  10467. unsigned numArgs = args.ordinality();
  10468. assertex(numArgs != 0);
  10469. IHqlExpression * ret = &OLINK(args.item(numArgs-1));
  10470. for (unsigned idx = numArgs-1; idx-- != 0; )
  10471. ret = createValue(op, ret->getType(), &OLINK(args.item(idx)), ret);
  10472. return ret;
  10473. }
  10474. extern IHqlExpression *createRecord()
  10475. {
  10476. return new CHqlRecord();
  10477. }
  10478. extern IHqlExpression *createRecord(const HqlExprArray & fields)
  10479. {
  10480. CHqlRecord * record = new CHqlRecord();
  10481. ForEachItemIn(idx, fields)
  10482. {
  10483. IHqlExpression & cur = fields.item(idx);
  10484. record->addOperand(LINK(&cur));
  10485. }
  10486. return record->closeExpr();
  10487. }
  10488. extern IHqlExpression * createAssign(IHqlExpression * expr1, IHqlExpression * expr2)
  10489. {
  10490. return createValue(no_assign, makeVoidType(), expr1, expr2);
  10491. }
  10492. extern IHqlExpression *createConstant(bool constant)
  10493. {
  10494. if (constant)
  10495. return LINK(constantTrue);
  10496. return LINK(constantFalse);
  10497. }
  10498. extern IHqlExpression *createConstant(__int64 constant)
  10499. {
  10500. //return CHqlConstant::makeConstant(createIntValue(constant, 8, true));
  10501. // NOTE - we do not support large uint64 consts properly....
  10502. bool sign;
  10503. unsigned size;
  10504. if (constant >= 0)
  10505. {
  10506. if (constant < 256)
  10507. {
  10508. size = 1;
  10509. sign = constant < 128;
  10510. }
  10511. else if (constant < 65536)
  10512. {
  10513. size = 2;
  10514. sign = constant < 32768;
  10515. }
  10516. else if (constant < I64C(0x100000000))
  10517. {
  10518. size = 4;
  10519. sign = constant < 0x80000000;
  10520. }
  10521. else
  10522. {
  10523. size = 8;
  10524. sign = true;
  10525. }
  10526. }
  10527. else
  10528. {
  10529. sign = true;
  10530. if (constant >= -128)
  10531. size = 1;
  10532. else if (constant >= -32768)
  10533. size = 2;
  10534. else if (constant >= (signed __int32) 0x80000000)
  10535. size = 4;
  10536. else
  10537. size = 8;
  10538. }
  10539. return CHqlConstant::makeConstant(createIntValue(constant, size, sign));
  10540. }
  10541. extern IHqlExpression *createConstant(__int64 constant, ITypeInfo * type)
  10542. {
  10543. return createConstant(createIntValue(constant, type));
  10544. }
  10545. extern IHqlExpression *createConstant(double constant)
  10546. {
  10547. return CHqlConstant::makeConstant(createRealValue(constant, DEFAULT_REAL_SIZE));
  10548. }
  10549. extern IHqlExpression *createConstant(const char *constant)
  10550. {
  10551. return CHqlConstant::makeConstant(createStringValue(constant, strlen(constant)));
  10552. }
  10553. extern IHqlExpression *createConstant(IValue * constant)
  10554. {
  10555. return CHqlConstant::makeConstant(constant);
  10556. }
  10557. //This is called by the code generator when it needs to make an explicit call to an internal function, with arguments already translated.
  10558. extern IHqlExpression * createTranslatedExternalCall(IErrorReceiver * errors, IHqlExpression *func, HqlExprArray &actuals)
  10559. {
  10560. assertex(func->getOperator() == no_funcdef);
  10561. IHqlExpression * binder = func->queryChild(0);
  10562. assertex(binder->getOperator() == no_external);
  10563. return CHqlExternalCall::makeExternalCall(LINK(func), binder->getType(), actuals);
  10564. }
  10565. extern IHqlExpression *createExternalReference(IIdAtom * id, ITypeInfo *_type, IHqlExpression *props)
  10566. {
  10567. HqlExprArray attributes;
  10568. if (props)
  10569. {
  10570. props->unwindList(attributes, no_comma);
  10571. props->Release();
  10572. }
  10573. return CHqlExternal::makeExternalReference(id, _type, attributes)->closeExpr();
  10574. }
  10575. extern IHqlExpression *createExternalReference(IIdAtom * id, ITypeInfo *_type, HqlExprArray & attributes)
  10576. {
  10577. return CHqlExternal::makeExternalReference(id, _type, attributes)->closeExpr();
  10578. }
  10579. IHqlExpression * createExternalFuncdefFromInternal(IHqlExpression * funcdef)
  10580. {
  10581. IHqlExpression * body = funcdef->queryChild(0);
  10582. HqlExprArray attrs;
  10583. unwindChildren(attrs, body, 1);
  10584. if (body->isPure())
  10585. attrs.append(*createAttribute(pureAtom));
  10586. if (body->getInfoFlags() & HEFaction)
  10587. attrs.append(*createAttribute(actionAtom));
  10588. if (body->getInfoFlags() & HEFcontextDependentException)
  10589. attrs.append(*createAttribute(contextSensitiveAtom));
  10590. ITypeInfo * returnType = funcdef->queryType()->queryChildType();
  10591. OwnedHqlExpr externalExpr = createExternalReference(funcdef->queryId(), LINK(returnType), attrs);
  10592. return replaceChild(funcdef, 0, externalExpr);
  10593. }
  10594. extern IHqlExpression* createValue(node_operator op, HqlExprArray& operands) {
  10595. return CHqlExpressionWithType::makeExpression(op, NULL, operands);
  10596. }
  10597. extern IHqlExpression* createValue(node_operator op, ITypeInfo *_type, HqlExprArray& operands) {
  10598. return CHqlExpressionWithType::makeExpression(op, _type, operands);
  10599. }
  10600. extern IHqlExpression *createValue(node_operator op, IHqlExpression *p1) {
  10601. return CHqlExpressionWithType::makeExpression(op, NULL, p1, NULL);
  10602. }
  10603. extern IHqlExpression* createConstant(int ival) {
  10604. return CHqlConstant::makeConstant(createIntValue(ival, DEFAULT_INT_SIZE, true));
  10605. }
  10606. extern IHqlExpression* createBoolExpr(node_operator op, HqlExprArray& operands) {
  10607. return CHqlExpressionWithType::makeExpression(op, makeBoolType(), operands);
  10608. }
  10609. extern IHqlExpression *createWrapper(node_operator op, IHqlExpression * e)
  10610. {
  10611. ITypeInfo * type = e->queryType();
  10612. if (type)
  10613. {
  10614. switch (type->getTypeCode())
  10615. {
  10616. case type_row:
  10617. return createRow(op, e);
  10618. case type_table:
  10619. case type_groupedtable:
  10620. return createDataset(op, e, NULL);
  10621. case type_dictionary:
  10622. return createDictionary(op, e, NULL);
  10623. }
  10624. }
  10625. return createValue(op, LINK(type), e);
  10626. }
  10627. IHqlExpression *createWrapper(node_operator op, ITypeInfo * type, HqlExprArray & args)
  10628. {
  10629. if (type)
  10630. {
  10631. switch (type->getTypeCode())
  10632. {
  10633. case type_row:
  10634. return createRow(op, args);
  10635. case type_dictionary:
  10636. return createDictionary(op, args);
  10637. case type_table:
  10638. case type_groupedtable:
  10639. return createDataset(op, args);
  10640. }
  10641. }
  10642. return createValue(op, LINK(type), args);
  10643. }
  10644. extern HQL_API IHqlExpression *createWrapper(node_operator op, IHqlExpression * expr, IHqlExpression * arg)
  10645. {
  10646. HqlExprArray args;
  10647. args.append(*expr);
  10648. if (arg)
  10649. {
  10650. arg->unwindList(args, no_comma);
  10651. arg->Release();
  10652. }
  10653. return createWrapper(op, expr->queryType(), args);
  10654. }
  10655. IHqlExpression *createWrappedExpr(IHqlExpression * expr, node_operator op, HqlExprArray & args)
  10656. {
  10657. args.add(*LINK(expr), 0);
  10658. return createWrapper(op, expr->queryType(), args);
  10659. }
  10660. IHqlExpression *createWrapper(node_operator op, HqlExprArray & args)
  10661. {
  10662. return createWrapper(op, args.item(0).queryType(), args);
  10663. }
  10664. extern IHqlExpression *createDatasetFromRow(IHqlExpression * ownedRow)
  10665. {
  10666. //The follow generates better code, but causes problems with several examples in the ln regression suite
  10667. //So disabled until can investigate more
  10668. if (false && isSelectFirstRow(ownedRow))
  10669. {
  10670. IHqlExpression * childDs = ownedRow->queryChild(0);
  10671. if (hasSingleRow(childDs))
  10672. {
  10673. OwnedHqlExpr releaseRow = ownedRow;
  10674. return LINK(childDs);
  10675. }
  10676. }
  10677. return createDataset(no_datasetfromrow, ownedRow); //, createUniqueId());
  10678. }
  10679. inline IHqlExpression * normalizeSelectLhs(IHqlExpression * lhs, bool & isNew)
  10680. {
  10681. loop
  10682. {
  10683. switch (lhs->getOperator())
  10684. {
  10685. case no_newrow:
  10686. assertex(!isNew);
  10687. isNew = true;
  10688. lhs = lhs->queryChild(0);
  10689. break; // round the loop again
  10690. case no_activerow:
  10691. isNew = false;
  10692. lhs = lhs->queryChild(0);
  10693. break; // round the loop again
  10694. case no_left:
  10695. case no_right:
  10696. case no_top:
  10697. case no_activetable:
  10698. case no_self:
  10699. case no_selfref:
  10700. isNew = false;
  10701. return lhs;
  10702. case no_select:
  10703. if (isNew && isAlwaysActiveRow(lhs))
  10704. isNew = false;
  10705. return lhs;
  10706. case no_selectnth:
  10707. case no_createrow:
  10708. assertex(isAlwaysNewRow(lhs));
  10709. //Ensure selects of these expressions always have new set - it saves problems when an
  10710. //unnormalized tree is walked or transformed.
  10711. //IF/PROJECTROW are not includes since they could be folded to an active selector
  10712. isNew = true;
  10713. return lhs;
  10714. default:
  10715. return lhs;
  10716. }
  10717. }
  10718. }
  10719. inline void checkRhsSelect(IHqlExpression * rhs)
  10720. {
  10721. #ifdef _DEBUG
  10722. node_operator rhsOp = rhs->getOperator();
  10723. assertex(rhsOp == no_field || rhsOp == no_ifblock || rhsOp == no_indirect);
  10724. #endif
  10725. }
  10726. extern IHqlExpression * createSelectExpr(IHqlExpression * _lhs, IHqlExpression * rhs, bool _isNew)
  10727. {
  10728. OwnedHqlExpr lhs = _lhs;
  10729. bool isNew = _isNew;
  10730. IHqlExpression * normalLhs = normalizeSelectLhs(lhs, isNew);
  10731. IHqlExpression * newAttr = isNew ? newSelectAttrExpr : NULL;
  10732. checkRhsSelect(rhs);
  10733. type_t t = rhs->queryType()->getTypeCode();
  10734. if (t == type_table || t == type_groupedtable)
  10735. return createDataset(no_select, LINK(normalLhs), createComma(rhs, LINK(newAttr)));
  10736. if (t == type_dictionary)
  10737. return createDictionary(no_select, LINK(normalLhs), createComma(rhs, LINK(newAttr)));
  10738. if (t == type_row)
  10739. return createRow(no_select, LINK(normalLhs), createComma(rhs, LINK(newAttr)));
  10740. return CHqlSelectBaseExpression::makeSelectExpression(LINK(normalLhs), rhs, LINK(newAttr));
  10741. }
  10742. static IHqlExpression * doCreateSelectExpr(HqlExprArray & args)
  10743. {
  10744. IHqlExpression * rhs = &args.item(1);
  10745. checkRhsSelect(rhs);
  10746. type_t t = rhs->queryType()->getTypeCode();
  10747. if (t == type_table || t == type_groupedtable)
  10748. return createDataset(no_select, args);
  10749. if (t == type_dictionary)
  10750. return createDictionary(no_select, args);
  10751. if (t == type_row)
  10752. return createRow(no_select, args);
  10753. return CHqlSelectBaseExpression::makeSelectExpression(args);
  10754. }
  10755. extern IHqlExpression * createSelectExpr(HqlExprArray & args)
  10756. {
  10757. IHqlExpression * lhs = &args.item(0);
  10758. bool isNew = false;
  10759. for (unsigned i=2; i < args.ordinality(); i++)
  10760. {
  10761. if (args.item(i).queryName() == newAtom)
  10762. {
  10763. isNew = true;
  10764. args.remove(i);
  10765. break;
  10766. }
  10767. }
  10768. IHqlExpression * normalLhs = normalizeSelectLhs(lhs, isNew);
  10769. if (lhs != normalLhs)
  10770. args.replace(*LINK(normalLhs), 0);
  10771. if (isNew)
  10772. args.append(*LINK(newSelectAttrExpr));
  10773. return doCreateSelectExpr(args);
  10774. }
  10775. IHqlExpression * ensureDataset(IHqlExpression * expr)
  10776. {
  10777. if (expr->isDataset())
  10778. return LINK(expr);
  10779. if (expr->isDatarow())
  10780. return createDatasetFromRow(LINK(expr));
  10781. throwUnexpected();
  10782. }
  10783. extern bool isAlwaysNewRow(IHqlExpression * expr)
  10784. {
  10785. switch (expr->getOperator())
  10786. {
  10787. case no_createrow:
  10788. case no_selectnth:
  10789. return true;
  10790. }
  10791. return false;
  10792. }
  10793. extern bool isAlwaysActiveRow(IHqlExpression * expr)
  10794. {
  10795. switch (expr->getOperator())
  10796. {
  10797. case no_activerow:
  10798. case no_left:
  10799. case no_right:
  10800. case no_top:
  10801. case no_activetable:
  10802. case no_self:
  10803. case no_selfref:
  10804. return true;
  10805. case no_select:
  10806. if (expr->isDataset())
  10807. return false;
  10808. return isAlwaysActiveRow(expr->queryChild(0));
  10809. }
  10810. return false;
  10811. }
  10812. IHqlExpression * ensureActiveRow(IHqlExpression * expr)
  10813. {
  10814. if (isAlwaysActiveRow(expr))
  10815. return LINK(expr);
  10816. return createRow(no_activerow, LINK(expr->queryNormalizedSelector()));
  10817. }
  10818. IHqlExpression * ensureSerialized(IHqlExpression * expr, IAtom * serialForm)
  10819. {
  10820. ITypeInfo * type = expr->queryType();
  10821. Owned<ITypeInfo> serialType = getSerializedForm(type, serialForm);
  10822. if (type == serialType)
  10823. return LINK(expr);
  10824. HqlExprArray args;
  10825. args.append(*LINK(expr));
  10826. args.append(*createAttribute(serialForm));
  10827. return createWrapper(no_serialize, serialType, args);
  10828. }
  10829. IHqlExpression * ensureDeserialized(IHqlExpression * expr, ITypeInfo * type, IAtom * serialForm)
  10830. {
  10831. assertex(type->getTypeCode() != type_record);
  10832. Owned<ITypeInfo> serialType = getSerializedForm(type, serialForm);
  10833. if (queryUnqualifiedType(type) == queryUnqualifiedType(serialType))
  10834. return LINK(expr);
  10835. assertRecordTypesMatch(expr->queryType(), serialType);
  10836. HqlExprArray args;
  10837. args.append(*LINK(expr));
  10838. args.append(*LINK(queryOriginalRecord(type)));
  10839. args.append(*createAttribute(serialForm));
  10840. //MORE: I may prefer to create a project instead of a serialize...
  10841. return createWrapper(no_deserialize, type, args);
  10842. }
  10843. bool isDummySerializeDeserialize(IHqlExpression * expr)
  10844. {
  10845. node_operator op = expr->getOperator();
  10846. if ((op != no_serialize) && (op != no_deserialize))
  10847. return false;
  10848. IHqlExpression * child = expr->queryChild(0);
  10849. node_operator childOp = child->getOperator();
  10850. if ((childOp != no_serialize) && (childOp != no_deserialize))
  10851. return false;
  10852. if (op == childOp)
  10853. return false;
  10854. //MORE:? Need to check the serialization form?
  10855. if (expr->queryType() != child->queryChild(0)->queryType())
  10856. return false;
  10857. return true;
  10858. }
  10859. bool isRedundantGlobalScope(IHqlExpression * expr)
  10860. {
  10861. assertex(expr->getOperator() == no_globalscope);
  10862. IHqlExpression * child = expr->queryChild(0);
  10863. if (child->getOperator() != no_globalscope)
  10864. return false;
  10865. if (expr->hasAttribute(optAtom) && !child->hasAttribute(optAtom))
  10866. return false;
  10867. return true;
  10868. }
  10869. bool isIndependentOfScope(IHqlExpression * expr)
  10870. {
  10871. return expr->isIndependentOfScope();
  10872. }
  10873. bool canEvaluateInScope(const HqlExprCopyArray & activeScopes, const HqlExprCopyArray & required)
  10874. {
  10875. ForEachItemIn(i, required)
  10876. {
  10877. if (!activeScopes.contains(required.item(i)))
  10878. return false;
  10879. }
  10880. return true;
  10881. }
  10882. bool canEvaluateInScope(const HqlExprCopyArray & activeScopes, IHqlExpression * expr)
  10883. {
  10884. HqlExprCopyArray scopesUsed;
  10885. expr->gatherTablesUsed(NULL, &scopesUsed);
  10886. return canEvaluateInScope(activeScopes, scopesUsed);
  10887. }
  10888. bool exprReferencesDataset(IHqlExpression * expr, IHqlExpression * dataset)
  10889. {
  10890. return expr->usesSelector(dataset->queryNormalizedSelector());
  10891. }
  10892. void gatherChildTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope, IHqlExpression * expr, unsigned firstChild)
  10893. {
  10894. unsigned max = expr->numChildren();
  10895. for (unsigned i=firstChild; i < max; i++)
  10896. expr->queryChild(i)->gatherTablesUsed(newScope, inScope);
  10897. }
  10898. extern IHqlScope *createService()
  10899. {
  10900. return new CHqlLocalScope(no_service, NULL, NULL);
  10901. }
  10902. extern IHqlScope *createScope()
  10903. {
  10904. return new CHqlLocalScope(no_scope, NULL, NULL);
  10905. }
  10906. extern IHqlScope *createPrivateScope()
  10907. {
  10908. return new CHqlLocalScope(no_privatescope, NULL, NULL);
  10909. }
  10910. extern IHqlScope *createPrivateScope(IHqlScope * scope)
  10911. {
  10912. return new CHqlLocalScope(no_privatescope, scope->queryId(), scope->queryFullName());
  10913. }
  10914. extern IHqlScope* createScope(IHqlScope* scope)
  10915. {
  10916. return new CHqlLocalScope(scope);
  10917. }
  10918. extern IHqlScope* createVirtualScope()
  10919. {
  10920. return new CHqlVirtualScope(NULL, NULL);
  10921. }
  10922. extern IHqlScope* createForwardScope(IHqlScope * parentScope, HqlGramCtx * parentCtx, HqlParseContext & parseCtx)
  10923. {
  10924. return new CHqlForwardScope(parentScope, parentCtx, parseCtx);
  10925. }
  10926. extern IHqlScope* createConcreteScope()
  10927. {
  10928. return new CHqlLocalScope(no_concretescope, NULL, NULL);
  10929. }
  10930. extern IHqlScope* createVirtualScope(IIdAtom * id, const char * fullName)
  10931. {
  10932. return new CHqlVirtualScope(id, fullName);
  10933. }
  10934. extern IHqlScope* createLibraryScope()
  10935. {
  10936. return new CHqlLocalScope(no_libraryscope, NULL, NULL);
  10937. }
  10938. extern IHqlRemoteScope *createRemoteScope(IIdAtom * id, const char * fullName, IEclRepositoryCallback *ds, IProperties* props, IFileContents * text, bool lazy, IEclSource * eclSource)
  10939. {
  10940. assertex(fullName || !id);
  10941. return new CHqlRemoteScope(id, fullName, ds, props, text, lazy, eclSource);
  10942. }
  10943. IHqlExpression * populateScopeAndClose(IHqlScope * scope, const HqlExprArray & children, const HqlExprArray & symbols)
  10944. {
  10945. IHqlExpression * scopeExpr = queryExpression(scope);
  10946. ForEachItemIn(i1, children)
  10947. scopeExpr->addOperand(LINK(&children.item(i1)));
  10948. ForEachItemIn(i2, symbols)
  10949. scope->defineSymbol(&OLINK(symbols.item(i2)));
  10950. return scopeExpr->closeExpr();
  10951. }
  10952. extern HQL_API IHqlExpression* createTemplateFunctionContext(IHqlExpression* expr, IHqlScope* scope)
  10953. {
  10954. IHqlExpression* e = new CHqlTemplateFunctionContext(expr, scope);
  10955. return e->closeExpr();
  10956. }
  10957. extern IHqlExpression* createFieldMap(IHqlExpression* ds, IHqlExpression* map)
  10958. {
  10959. return createDataset(no_fieldmap, ds, map);
  10960. }
  10961. extern IHqlExpression * createCompound(IHqlExpression * expr1, IHqlExpression * expr2)
  10962. {
  10963. if (!expr1)
  10964. return expr2;
  10965. if (!expr2)
  10966. return expr1;
  10967. assertex(expr1->queryType()->getTypeCode() == type_void);
  10968. if (!expr2->isFunction())
  10969. {
  10970. if (expr2->isDataset())
  10971. return createDataset(no_compound, expr1, expr2);
  10972. if (expr2->isDatarow())
  10973. return createRow(no_compound, expr1, expr2);
  10974. }
  10975. return createValue(no_compound, expr2->getType(), expr1, expr2);
  10976. }
  10977. extern IHqlExpression * createCompound(const HqlExprArray & actions)
  10978. {
  10979. IHqlExpression * expr = NULL;
  10980. ForEachItemInRev(idx, actions)
  10981. expr = createCompound(&OLINK(actions.item(idx)), expr);
  10982. return expr;
  10983. }
  10984. extern IHqlExpression * createActionList(node_operator op, const HqlExprArray & actions)
  10985. {
  10986. switch (actions.ordinality())
  10987. {
  10988. case 0:
  10989. return createValue(no_null, makeVoidType());
  10990. case 1:
  10991. return LINK(&actions.item(0));
  10992. }
  10993. return createValueSafe(op, makeVoidType(), actions);
  10994. }
  10995. extern IHqlExpression * createActionList(const HqlExprArray & actions)
  10996. {
  10997. return createActionList(no_actionlist, actions);
  10998. }
  10999. extern void ensureActions(HqlExprArray & actions, unsigned first, unsigned last)
  11000. {
  11001. for (unsigned i=first; i < last; i++)
  11002. {
  11003. IHqlExpression & cur = actions.item(i);
  11004. if (!cur.isAction())
  11005. actions.replace(*createValue(no_evaluate_stmt, makeVoidType(), LINK(&cur)), i);
  11006. }
  11007. }
  11008. extern void ensureActions(HqlExprArray & actions)
  11009. {
  11010. ensureActions(actions, 0, actions.ordinality());
  11011. }
  11012. extern IHqlExpression * createActionList(node_operator op, const HqlExprArray & actions, unsigned from, unsigned to)
  11013. {
  11014. switch (to-from)
  11015. {
  11016. case 0:
  11017. return createValue(no_null, makeVoidType());
  11018. case 1:
  11019. return LINK(&actions.item(from));
  11020. }
  11021. return createValueSafe(op, makeVoidType(), actions, from, to);
  11022. }
  11023. extern IHqlExpression * createActionList(const HqlExprArray & actions, unsigned from, unsigned to)
  11024. {
  11025. return createActionList(no_actionlist, actions, from, to);
  11026. }
  11027. extern IHqlExpression * createCompound(node_operator op, const HqlExprArray & actions)
  11028. {
  11029. if (op == no_compound)
  11030. return createCompound(actions);
  11031. else
  11032. return createActionList(actions);
  11033. }
  11034. extern IHqlExpression * createComma(IHqlExpression * expr1, IHqlExpression * expr2)
  11035. {
  11036. if (!expr1)
  11037. return expr2;
  11038. if (!expr2)
  11039. return expr1;
  11040. return createValue(no_comma, expr1->getType(), expr1, expr2);
  11041. }
  11042. extern IHqlExpression * createComma(IHqlExpression * expr1, IHqlExpression * expr2, IHqlExpression * expr3)
  11043. {
  11044. return createComma(expr1, createComma(expr2, expr3));
  11045. }
  11046. extern IHqlExpression * createComma(IHqlExpression * expr1, IHqlExpression * expr2, IHqlExpression * expr3, IHqlExpression * expr4)
  11047. {
  11048. return createComma(expr1, createComma(expr2, createComma(expr3, expr4)));
  11049. }
  11050. static IHqlExpression * createComma(const HqlExprArray & exprs, unsigned first, unsigned last)
  11051. {
  11052. if (first +1 == last)
  11053. return &OLINK(exprs.item(first));
  11054. unsigned mid = (first+last)/2;
  11055. return createComma(createComma(exprs, first, mid), createComma(exprs, mid, last));
  11056. }
  11057. extern IHqlExpression * createComma(const HqlExprArray & exprs)
  11058. {
  11059. //Create a balanced tree instead of unbalanced...
  11060. unsigned max = exprs.ordinality();
  11061. if (max == 0)
  11062. return NULL;
  11063. else if (max == 1)
  11064. return &OLINK(exprs.item(0));
  11065. return createComma(exprs, 0, max);
  11066. }
  11067. IHqlExpression * createBalanced(node_operator op, ITypeInfo * type, const HqlExprArray & exprs, unsigned first, unsigned last)
  11068. {
  11069. if (first +1 == last)
  11070. return &OLINK(exprs.item(first));
  11071. unsigned mid = (first+last)/2;
  11072. IHqlExpression * left = createBalanced(op, type, exprs, first, mid);
  11073. IHqlExpression * right = createBalanced(op, type, exprs, mid, last);
  11074. return createValue(op, LINK(type), left, right);
  11075. }
  11076. extern IHqlExpression * createBalanced(node_operator op, ITypeInfo * type, const HqlExprArray & exprs)
  11077. {
  11078. //Create a balanced tree instead of unbalanced...
  11079. unsigned max = exprs.ordinality();
  11080. if (max == 0)
  11081. return NULL;
  11082. else if (max == 1)
  11083. return &OLINK(exprs.item(0));
  11084. return createBalanced(op, type, exprs, 0, max);
  11085. }
  11086. extern IHqlExpression * createUnbalanced(node_operator op, ITypeInfo * type, const HqlExprArray & exprs)
  11087. {
  11088. unsigned max = exprs.ordinality();
  11089. if (max == 0)
  11090. return NULL;
  11091. LinkedHqlExpr ret = &exprs.item(0);
  11092. for (unsigned i=1; i < max; i++)
  11093. ret.setown(createValue(op, LINK(type), ret.getClear(), LINK(&exprs.item(i))));
  11094. return ret.getClear();
  11095. }
  11096. IHqlExpression * extendConditionOwn(node_operator op, IHqlExpression * l, IHqlExpression * r)
  11097. {
  11098. if (!r) return l;
  11099. IValue * rvalue = r->queryValue();
  11100. if (rvalue)
  11101. {
  11102. bool val = rvalue->getBoolValue();
  11103. switch (op)
  11104. {
  11105. case no_or:
  11106. //x or true = true, x or false = x
  11107. if (val)
  11108. {
  11109. ::Release(l);
  11110. return r;
  11111. }
  11112. else
  11113. {
  11114. r->Release();
  11115. return l;
  11116. }
  11117. break;
  11118. case no_and:
  11119. //x and true = x, x and false = false
  11120. if (val)
  11121. {
  11122. r->Release();
  11123. return l;
  11124. }
  11125. else
  11126. {
  11127. ::Release(l);
  11128. return r;
  11129. }
  11130. break;
  11131. }
  11132. }
  11133. if (!l) return r;
  11134. return createValue(op, l->getType(), l, r);
  11135. }
  11136. extern IValue * createNullValue(ITypeInfo * type)
  11137. {
  11138. IValue * null;
  11139. switch (type->getTypeCode())
  11140. {
  11141. case type_alien:
  11142. {
  11143. IHqlAlienTypeInfo * alien = queryAlienType(type);
  11144. type = alien->queryPhysicalType();
  11145. null = blank->castTo(type);
  11146. }
  11147. break;
  11148. case type_bitfield:
  11149. null = createNullValue(type->queryPromotedType());
  11150. break;
  11151. default:
  11152. null = blank->castTo(type);
  11153. break;
  11154. }
  11155. assertex(null);
  11156. return null;
  11157. }
  11158. extern HQL_API IHqlExpression * createNullScope()
  11159. {
  11160. return queryExpression(createScope())->closeExpr();
  11161. }
  11162. extern HQL_API IHqlExpression * createNullExpr(ITypeInfo * type)
  11163. {
  11164. switch (type->getTypeCode())
  11165. {
  11166. case type_set:
  11167. {
  11168. ITypeInfo * childType = type->queryChildType();
  11169. if (childType && isDatasetType(childType))
  11170. return createValue(no_datasetlist, LINK(type));
  11171. return createValue(no_list, LINK(type));
  11172. }
  11173. case type_groupedtable:
  11174. {
  11175. ITypeInfo * recordType = queryRecordType(type);
  11176. IHqlExpression * record = queryExpression(recordType);
  11177. return createDataset(no_null, LINK(record), createGroupedAttribute(NULL));
  11178. }
  11179. case type_table:
  11180. {
  11181. ITypeInfo * recordType = queryRecordType(type);
  11182. IHqlExpression * record = queryExpression(recordType);
  11183. IHqlExpression * attr = queryAttribute(type, _linkCounted_Atom);
  11184. return createDataset(no_null, LINK(record), LINK(attr));
  11185. }
  11186. case type_dictionary:
  11187. {
  11188. ITypeInfo * recordType = queryRecordType(type);
  11189. IHqlExpression * record = queryExpression(recordType);
  11190. IHqlExpression * attr = queryAttribute(type, _linkCounted_Atom);
  11191. return createDictionary(no_null, LINK(record), LINK(attr));
  11192. }
  11193. case type_row:
  11194. #if 0
  11195. {
  11196. OwnedHqlExpr nullTransform = createClearTransform(queryOriginalRecord(type));
  11197. return createRow(no_createrow, LINK(nullTransform));
  11198. }
  11199. #endif
  11200. case type_record:
  11201. return createRow(no_null, LINK(queryRecord(type)));
  11202. case type_int:
  11203. {
  11204. unsigned size = type->getSize();
  11205. unsigned isSigned = type->isSigned() ? 0 : 1;
  11206. CriticalBlock block(*nullIntCS);
  11207. IHqlExpression * null = nullIntValue[size][isSigned];
  11208. if (!null)
  11209. {
  11210. null = createConstant(blank->castTo(type));
  11211. nullIntValue[size][isSigned] = null;
  11212. }
  11213. return LINK(null);
  11214. }
  11215. case type_void:
  11216. return createValue(no_null, makeVoidType());
  11217. case type_scope:
  11218. return createNullScope();
  11219. case type_sortlist:
  11220. return createValue(no_sortlist, LINK(type));
  11221. case type_transform:
  11222. return createNullTransform(queryRecord(type));
  11223. default:
  11224. return createConstant(createNullValue(type));
  11225. }
  11226. }
  11227. extern HQL_API IHqlExpression * createNullExpr(IHqlExpression * expr)
  11228. {
  11229. if (expr->getOperator()==no_select)
  11230. return createNullExpr(expr->queryChild(1));
  11231. IHqlExpression * defaultValue = queryAttributeChild(expr, defaultAtom, 0);
  11232. if (defaultValue)
  11233. return LINK(defaultValue);
  11234. return createNullExpr(expr->queryType());
  11235. }
  11236. extern HQL_API IHqlExpression * createPureVirtual(ITypeInfo * type)
  11237. {
  11238. if (type)
  11239. {
  11240. switch (type->getTypeCode())
  11241. {
  11242. case type_table:
  11243. return createDataset(no_purevirtual, LINK(queryOriginalRecord(type)));
  11244. case type_groupedtable:
  11245. return createDataset(no_purevirtual, LINK(queryOriginalRecord(type)), createAttribute(groupedAtom));
  11246. case type_dictionary:
  11247. return createDictionary(no_purevirtual, LINK(queryOriginalRecord(type)), createAttribute(groupedAtom));
  11248. case type_row:
  11249. case type_record:
  11250. return createRow(no_purevirtual, LINK(queryOriginalRecord(type)));
  11251. case type_scope:
  11252. //Could turn this into an interface - needed if we support nested modules
  11253. throwUnexpected();
  11254. default:
  11255. return createValue(no_purevirtual, LINK(type));
  11256. }
  11257. }
  11258. else
  11259. return createValue(no_purevirtual, makeIntType(8, true));
  11260. }
  11261. extern HQL_API bool isNullExpr(IHqlExpression * expr, IHqlExpression * field)
  11262. {
  11263. ITypeInfo * exprType = expr->queryType();
  11264. ITypeInfo * fieldType = field->queryType();
  11265. if (exprType->getTypeCode() != fieldType->getTypeCode())
  11266. return false;
  11267. IValue * value = expr->queryValue();
  11268. switch (fieldType->getTypeCode())
  11269. {
  11270. case type_boolean:
  11271. case type_int:
  11272. case type_swapint:
  11273. case type_date:
  11274. case type_enumerated:
  11275. case type_bitfield:
  11276. case type_data:
  11277. case type_string:
  11278. case type_varstring:
  11279. case type_unicode:
  11280. case type_varunicode:
  11281. case type_utf8:
  11282. case type_qstring:
  11283. case type_decimal:
  11284. case type_real:
  11285. case type_alien:
  11286. case type_set:
  11287. {
  11288. if (!value)
  11289. return false;
  11290. OwnedHqlExpr null = createNullExpr(field);
  11291. OwnedHqlExpr castValue = ensureExprType(expr, fieldType);
  11292. return null->queryBody() == castValue->queryBody();
  11293. }
  11294. case type_row:
  11295. case type_table:
  11296. case type_groupedtable:
  11297. return (expr->getOperator() == no_null);
  11298. default:
  11299. return false;
  11300. }
  11301. }
  11302. extern HQL_API IHqlExpression * createConstantOne()
  11303. {
  11304. return LINK(cachedOne);
  11305. }
  11306. extern HQL_API IHqlExpression * createLocalAttribute()
  11307. {
  11308. return LINK(cachedLocalAttribute);
  11309. }
  11310. IHqlExpression * cloneOrLink(IHqlExpression * expr, HqlExprArray & children)
  11311. {
  11312. unsigned prevNum = expr->numChildren();
  11313. unsigned newNum = children.ordinality();
  11314. if (prevNum != newNum)
  11315. return expr->clone(children);
  11316. ForEachItemIn(idx, children)
  11317. {
  11318. if (&children.item(idx) != expr->queryChild(idx))
  11319. return expr->clone(children);
  11320. }
  11321. return LINK(expr);
  11322. }
  11323. IHqlExpression * createCompareExpr(node_operator op, IHqlExpression * l, IHqlExpression * r)
  11324. {
  11325. Owned<ITypeInfo> type = ::getPromotedECLCompareType(l->queryType(), r->queryType());
  11326. IHqlExpression * ret = createValue(op, makeBoolType(), ensureExprType(l, type), ensureExprType(r, type));
  11327. l->Release();
  11328. r->Release();
  11329. return ret;
  11330. }
  11331. IHqlExpression * createNullDataset(IHqlExpression * ds)
  11332. {
  11333. IHqlExpression * attr = isGrouped(ds) ? createGroupedAttribute(NULL) : NULL;
  11334. return createDataset(no_null, LINK(ds->queryRecord()), attr);
  11335. }
  11336. static IHqlExpression * doAttachWorkflowOwn(IHqlExpression * value, IHqlExpression * workflow)
  11337. {
  11338. if (!value->isFunction())
  11339. {
  11340. if (value->isDataset())
  11341. return createDataset(no_colon, value, LINK(workflow));
  11342. if (value->queryType()->getTypeCode() == type_row)
  11343. return createRow(no_colon, value, LINK(workflow));
  11344. if (value->isDictionary())
  11345. return createDictionary(no_colon, value, LINK(workflow));
  11346. }
  11347. //If a string value is stored, its type is a string of unknown length
  11348. //(because a different length string might be stored...)
  11349. Linked<ITypeInfo> type = value->queryType();
  11350. #ifdef STORED_CAN_CHANGE_LENGTH
  11351. switch (type->getTypeCode())
  11352. {
  11353. case type_qstring:
  11354. case type_varstring:
  11355. case type_string:
  11356. case type_data:
  11357. case type_unicode:
  11358. case type_varunicode:
  11359. case type_utf8:
  11360. type.setown(getStretchedType(UNKNOWN_LENGTH, type));
  11361. break;
  11362. }
  11363. #endif
  11364. return createValueF(no_colon, type.getClear(), value, LINK(workflow), NULL);
  11365. }
  11366. void processSectionPseudoWorkflow(SharedHqlExpr & expr, IHqlExpression * workflow, const HqlExprCopyArray * allActiveParameters)
  11367. {
  11368. //Section attributes are implemented by adding a sectionAnnotation to all datasets within a section that aren't
  11369. //included in the list of active parameters, or the datasets provided as parameters to the section
  11370. HqlSectionAnnotator annotator(workflow);
  11371. if (allActiveParameters)
  11372. {
  11373. ForEachItemIn(i1, *allActiveParameters)
  11374. {
  11375. IHqlExpression & cur = allActiveParameters->item(i1);
  11376. if (!cur.isFunction() && cur.isDataset())
  11377. annotator.noteInput(&cur);
  11378. }
  11379. }
  11380. ForEachChildFrom(i2, workflow, 1)
  11381. {
  11382. IHqlExpression * cur = workflow->queryChild(i2);
  11383. if (!cur->isFunction() && cur->isDataset())
  11384. annotator.noteInput(cur);
  11385. }
  11386. OwnedHqlExpr value = annotator.transform(expr);
  11387. expr.set(value);
  11388. }
  11389. static IHqlExpression * processPseudoWorkflow(SharedHqlExpr & expr, HqlExprArray & meta, IHqlExpression * workflow, const HqlExprCopyArray * allActiveParameters)
  11390. {
  11391. switch (workflow->getOperator())
  11392. {
  11393. case no_comma:
  11394. {
  11395. IHqlExpression * left = workflow->queryChild(0);
  11396. IHqlExpression * right = workflow->queryChild(1);
  11397. OwnedHqlExpr newLeft = processPseudoWorkflow(expr, meta, left, allActiveParameters);
  11398. OwnedHqlExpr newRight = processPseudoWorkflow(expr, meta, right, allActiveParameters);
  11399. if ((left != newLeft) || (right != newRight))
  11400. return createComma(newLeft.getClear(), newRight.getClear());
  11401. return LINK(workflow);
  11402. }
  11403. case no_attr:
  11404. {
  11405. IAtom * name = workflow->queryName();
  11406. if (name == sectionAtom)
  11407. {
  11408. processSectionPseudoWorkflow(expr, workflow, allActiveParameters);
  11409. return NULL;
  11410. }
  11411. else if ((name == deprecatedAtom) || (name == onWarningAtom))
  11412. {
  11413. meta.append(*LINK(workflow));
  11414. return NULL;
  11415. }
  11416. break;
  11417. }
  11418. }
  11419. return LINK(workflow);
  11420. }
  11421. IHqlExpression * attachWorkflowOwn(HqlExprArray & meta, IHqlExpression * _value, IHqlExpression * workflow, const HqlExprCopyArray * allActiveParameters)
  11422. {
  11423. if (!workflow)
  11424. return _value;
  11425. //For patterns, we only allow define(x), and we want it inserted inside the no_pat_instance.
  11426. //Really the latter should be added after the workflow.... Also convert define to the non workflow form to
  11427. //aid processing later.
  11428. OwnedHqlExpr value = _value;
  11429. if (value->getOperator() == no_pat_instance)
  11430. {
  11431. assertex(workflow->isAttribute() && workflow->queryName() == defineAtom);
  11432. IHqlExpression * pattern = value->queryChild(0);
  11433. HqlExprArray args;
  11434. args.append(*createValue(no_define, pattern->getType(), LINK(pattern), LINK(workflow->queryChild(0))));
  11435. unwindChildren(args, value, 1);
  11436. return value->clone(args);
  11437. }
  11438. if (value->getOperator() == no_outofline)
  11439. {
  11440. HqlExprArray args;
  11441. args.append(*attachWorkflowOwn(meta, LINK(value->queryChild(0)), workflow, allActiveParameters));
  11442. unwindChildren(args, value, 1);
  11443. return value->clone(args);
  11444. }
  11445. OwnedHqlExpr newWorkflow = processPseudoWorkflow(value, meta, workflow, allActiveParameters);
  11446. if (newWorkflow)
  11447. value.setown(doAttachWorkflowOwn(value.getClear(), newWorkflow));
  11448. return value.getClear();
  11449. }
  11450. //==============================================================================================================
  11451. static bool queryOriginalName(ITypeInfo* type, StringBuffer& s)
  11452. {
  11453. ITypeInfo * original = queryModifier(type, typemod_original);
  11454. if (original)
  11455. {
  11456. IHqlExpression * expr = (IHqlExpression *)original->queryModifierExtra();
  11457. if (expr->queryName())
  11458. {
  11459. s.append(expr->queryName());
  11460. return true;
  11461. }
  11462. }
  11463. return false;
  11464. }
  11465. void PrintLogExprTree(IHqlExpression *expr, const char *caption, bool full)
  11466. {
  11467. StringBuffer s;
  11468. toECL(expr, s, full);
  11469. s.append('\n');
  11470. if (caption)
  11471. PrintLog(caption);
  11472. else if (full)
  11473. s.insert(0, "\n");
  11474. PrintLogDirect(s.str());
  11475. }
  11476. //========This will go to IExpression implementations ======================================================================================================
  11477. static unsigned exportRecord(IPropertyTree *dataNode, IHqlExpression * record, unsigned & offset, bool flatten);
  11478. static unsigned exportRecord(IPropertyTree *dataNode, IHqlExpression * record, bool flatten);
  11479. static inline bool isdigit_or_underbar(unsigned char c)
  11480. {
  11481. return isdigit(c) || c=='_';
  11482. }
  11483. unsigned exportField(IPropertyTree *table, IHqlExpression *field, unsigned & offset, bool flatten)
  11484. {
  11485. if (field->isAttribute())
  11486. return 0;
  11487. IHqlExpression *defValue = field->queryChild(0);
  11488. IPropertyTree *f = createPTree("Field", ipt_caseInsensitive);
  11489. ITypeInfo * type = field->queryType();
  11490. if (type->getTypeCode() == type_row)
  11491. type = type->queryChildType();
  11492. f->setProp("@label", field->queryName()->getAtomNamePtr());
  11493. f->setProp("@name", field->queryName()->getAtomNamePtr());
  11494. f->setPropInt("@position", offset++);
  11495. if (defValue && !defValue->isAttribute() && defValue->getOperator()!=no_field && defValue->getOperator() != no_select)
  11496. {
  11497. StringBuffer ecl;
  11498. toECL(defValue, ecl, false);
  11499. while (ecl.length())
  11500. {
  11501. unsigned char c = ecl.charAt(ecl.length()-1);
  11502. if (isspace(c) || c==';')
  11503. ecl.setLength(ecl.length()-1);
  11504. else
  11505. break;
  11506. }
  11507. f->setProp("Expression", ecl.str());
  11508. }
  11509. f->setPropInt("@rawtype", getClarionResultType(type));
  11510. StringBuffer typeName;
  11511. if (!queryOriginalName(type, typeName))
  11512. type->getECLType(typeName);
  11513. f->setProp("@ecltype", typeName.str());
  11514. while (isdigit_or_underbar((unsigned char)typeName.charAt(typeName.length()-1)))
  11515. typeName.remove(typeName.length()-1, 1);
  11516. f->setProp("@type", typeName.str());
  11517. f = table->addPropTree(f->queryName(), f);
  11518. unsigned thisSize = type->getSize();
  11519. IHqlExpression * record = queryRecord(type);
  11520. if (record)
  11521. {
  11522. switch (type->getTypeCode())
  11523. {
  11524. case type_record:
  11525. case type_row:
  11526. f->setPropBool("@isRecord", true);
  11527. break;
  11528. case type_table:
  11529. case type_groupedtable:
  11530. f->setPropBool("@isDataset", true);
  11531. break;
  11532. }
  11533. if (flatten)
  11534. {
  11535. thisSize = exportRecord(table, record, offset, flatten);
  11536. IPropertyTree *end = createPTree("Field", ipt_caseInsensitive);
  11537. end->setPropBool("@isEnd", true);
  11538. end->setProp("@name", field->queryName()->getAtomNamePtr());
  11539. table->addPropTree(end->queryName(), end);
  11540. }
  11541. else
  11542. thisSize = exportRecord(f, record, flatten);
  11543. }
  11544. f->setPropInt("@size", thisSize);
  11545. return thisSize;
  11546. }
  11547. static unsigned exportRecord(IPropertyTree *dataNode, IHqlExpression * record, unsigned & offset, bool flatten)
  11548. {
  11549. //MORE: Nested
  11550. unsigned size = 0;
  11551. ForEachChild(idx, record)
  11552. {
  11553. IHqlExpression * cur = record->queryChild(idx);
  11554. unsigned thisSize = 0;
  11555. switch (cur->getOperator())
  11556. {
  11557. case no_field:
  11558. thisSize = exportField(dataNode, cur, offset, flatten);
  11559. break;
  11560. case no_record:
  11561. thisSize = exportRecord(dataNode, cur, offset, flatten);
  11562. break;
  11563. case no_ifblock:
  11564. {
  11565. if (flatten)
  11566. {
  11567. exportRecord(dataNode, cur->queryChild(1), offset, flatten);
  11568. }
  11569. else
  11570. {
  11571. IPropertyTree * ifblock = dataNode->addPropTree("IfBlock", createPTree("IfBlock", ipt_caseInsensitive));
  11572. ifblock->setPropInt("@position", idx);
  11573. exportRecord(ifblock, cur->queryChild(1), flatten);
  11574. size = UNKNOWN_LENGTH;
  11575. }
  11576. break;
  11577. }
  11578. }
  11579. if (size != UNKNOWN_LENGTH)
  11580. {
  11581. if (thisSize != UNKNOWN_LENGTH)
  11582. size += thisSize;
  11583. else
  11584. size = UNKNOWN_LENGTH;
  11585. }
  11586. }
  11587. return size;
  11588. }
  11589. static unsigned exportRecord(IPropertyTree *dataNode, IHqlExpression * record, bool flatten)
  11590. {
  11591. unsigned offset = 0;
  11592. return exportRecord(dataNode, record, offset, flatten);
  11593. }
  11594. StringBuffer &getExportName(IHqlExpression *table, StringBuffer &s)
  11595. {
  11596. StringBuffer tname;
  11597. if (table->getOperator()==no_table)
  11598. {
  11599. IHqlExpression *mode = table->queryChild(2);
  11600. StringBuffer lc;
  11601. s.append(mode->toString(lc).toLowerCase());
  11602. IValue *name = table->queryChild(0)->queryValue(); // MORE - should probably try to fold
  11603. name->getStringValue(tname);
  11604. }
  11605. else
  11606. {
  11607. s.append("logical");
  11608. tname.append(table->queryName());
  11609. }
  11610. if (tname.length())
  11611. {
  11612. tname.toLowerCase();
  11613. tname.setCharAt(0, (char)(tname.charAt(0) - 0x20));
  11614. }
  11615. return s.append(tname);
  11616. }
  11617. void exportMap(IPropertyTree *dataNode, IHqlExpression *destTable, IHqlExpression *sourceTable)
  11618. {
  11619. IPropertyTree *maps = dataNode->queryPropTree("./Map");
  11620. if (!maps)
  11621. {
  11622. maps = createPTree("Map", ipt_caseInsensitive);
  11623. dataNode->addPropTree("Map", maps);
  11624. }
  11625. IPropertyTree *map = createPTree("MapTables", ipt_caseInsensitive);
  11626. StringBuffer name;
  11627. map->setProp("@destTable", getExportName(destTable, name).str());
  11628. map->setProp("@sourceTable", getExportName(sourceTable, name.clear()).str());
  11629. maps->addPropTree("MapTables", map);
  11630. }
  11631. void exportData(IPropertyTree *data, IHqlExpression *table, bool flatten)
  11632. {
  11633. IPropertyTree *tt = NULL;
  11634. switch (table->getOperator())
  11635. {
  11636. case no_table:
  11637. {
  11638. IHqlExpression *mode = table->queryChild(2);
  11639. StringBuffer prefix;
  11640. mode->toString(prefix);
  11641. prefix.toLowerCase();
  11642. prefix.setCharAt(0, (char)(prefix.charAt(0) - 0x20));
  11643. tt = createPTree(StringBuffer(prefix).append("Table").str(), ipt_caseInsensitive);
  11644. StringBuffer name;
  11645. tt->setProp("@name", getExportName(table, name).str());
  11646. tt->setProp("@exported", table->isExported() ? "true" : "false");
  11647. unsigned size = exportRecord(tt, table->queryChild(1), flatten);
  11648. if (mode->getOperator()==no_flat)
  11649. tt->setPropInt("@recordLength", size);
  11650. data->addPropTree(tt->queryName(), tt);
  11651. break;
  11652. }
  11653. case no_usertable:
  11654. {
  11655. IHqlExpression *filter = NULL;
  11656. IHqlExpression *base = table->queryChild(0);
  11657. if (base->getOperator()==no_filter)
  11658. {
  11659. // MORE - filter can have multiple kids. We will lose all but the first
  11660. filter = base->queryChild(1);
  11661. base = base->queryChild(0);
  11662. }
  11663. exportMap(data, table, base);
  11664. exportData(data, base);
  11665. tt = createPTree("LogicalTable", ipt_caseInsensitive);
  11666. StringBuffer name;
  11667. tt->setProp("@name", getExportName(table, name).str());
  11668. tt->setProp("@exported", table->isExported() ? "true" : "false");
  11669. exportRecord(tt, table->queryChild(1), flatten);
  11670. if (filter)
  11671. {
  11672. StringBuffer ecl;
  11673. toECL(filter, ecl, false);
  11674. while (ecl.length())
  11675. {
  11676. unsigned char c = ecl.charAt(ecl.length()-1);
  11677. if (isspace(c) || c==';')
  11678. ecl.setLength(ecl.length()-1);
  11679. else
  11680. break;
  11681. }
  11682. tt->setProp("Filter", ecl.str());
  11683. }
  11684. data->addPropTree(tt->queryName(), tt);
  11685. break;
  11686. }
  11687. case no_record:
  11688. {
  11689. exportRecord(data, table, flatten);
  11690. break;
  11691. }
  11692. case no_select:
  11693. {
  11694. unsigned offset = 0;
  11695. exportField(data, table->queryChild(1), offset, flatten);
  11696. break;
  11697. }
  11698. case no_field:
  11699. {
  11700. unsigned offset = 0;
  11701. exportField(data, table, offset, flatten);
  11702. break;
  11703. }
  11704. default:
  11705. UNIMPLEMENTED;
  11706. break;
  11707. }
  11708. }
  11709. //---------------------------------------------------------------------------
  11710. static bool exprContainsCounter(RecursionChecker & checker, IHqlExpression * expr, IHqlExpression * counter)
  11711. {
  11712. if (checker.alreadyVisited(expr))
  11713. return false;
  11714. checker.setVisited(expr);
  11715. switch (expr->getOperator())
  11716. {
  11717. case no_field:
  11718. case no_attr:
  11719. case no_attr_expr:
  11720. case no_attr_link:
  11721. return false;
  11722. case no_counter:
  11723. return (expr == counter);
  11724. case no_select:
  11725. {
  11726. IHqlExpression * ds = expr->queryChild(0);
  11727. if (isNewSelector(expr))
  11728. return exprContainsCounter(checker, ds, counter);
  11729. return false;
  11730. }
  11731. }
  11732. ForEachChild(idx, expr)
  11733. if (exprContainsCounter(checker, expr->queryChild(idx), counter))
  11734. return true;
  11735. return false;
  11736. }
  11737. bool transformContainsCounter(IHqlExpression * transform, IHqlExpression * counter)
  11738. {
  11739. RecursionChecker checker;
  11740. return exprContainsCounter(checker, transform, counter);
  11741. }
  11742. //==============================================================================================================
  11743. static IHqlExpression * applyInstantEclLimit(IHqlExpression * expr, unsigned limit)
  11744. {
  11745. if (expr->getOperator() == no_selectfields)
  11746. {
  11747. //Legacy artefact. no_selectfield should be removed.
  11748. HqlExprArray args;
  11749. args.append(*applyInstantEclLimit(expr->queryChild(0), limit));
  11750. unwindChildren(args, expr, 1);
  11751. args.append(*createUniqueId());
  11752. return expr->clone(args);
  11753. }
  11754. if (expr->isDataset())
  11755. {
  11756. if (limit && (expr->getOperator() != no_choosen))
  11757. return createDataset(no_choosen, LINK(expr), createConstant((__int64) limit));
  11758. }
  11759. return LINK(expr);
  11760. }
  11761. static IHqlExpression *doInstantEclTransformation(IHqlExpression * subquery, unsigned limit)
  11762. {
  11763. if (subquery->getOperator()==no_output && !queryRealChild(subquery, 1) && !subquery->hasAttribute(allAtom))
  11764. {
  11765. IHqlExpression * ds = subquery->queryChild(0);
  11766. OwnedHqlExpr limitedDs = applyInstantEclLimit(ds, limit);
  11767. return replaceChild(subquery, 0, limitedDs);
  11768. }
  11769. return LINK(subquery);
  11770. }
  11771. static IHqlExpression * walkInstantEclTransformations(IHqlExpression * expr, unsigned limit)
  11772. {
  11773. switch (expr->getOperator())
  11774. {
  11775. case no_compound:
  11776. case no_comma:
  11777. case no_sequential:
  11778. case no_parallel:
  11779. case no_orderedactionlist:
  11780. case no_actionlist:
  11781. case no_if:
  11782. case no_case:
  11783. case no_map:
  11784. case no_colon:
  11785. case no_chooseds:
  11786. {
  11787. HqlExprArray args;
  11788. ForEachChild(i, expr)
  11789. args.append(*walkInstantEclTransformations(expr->queryChild(i), limit));
  11790. return expr->clone(args);
  11791. }
  11792. case no_output:
  11793. return doInstantEclTransformation(expr, limit);
  11794. }
  11795. return LINK(expr);
  11796. }
  11797. static IHqlExpression * walkRootInstantEclTransformations(IHqlExpression * expr, unsigned limit)
  11798. {
  11799. switch (expr->getOperator())
  11800. {
  11801. case no_compound:
  11802. case no_comma:
  11803. {
  11804. HqlExprArray args;
  11805. ForEachChild(i, expr)
  11806. args.append(*walkRootInstantEclTransformations(expr->queryChild(i), limit));
  11807. return expr->clone(args);
  11808. }
  11809. }
  11810. if (expr->isDataset())
  11811. return applyInstantEclLimit(expr, limit);
  11812. return walkInstantEclTransformations(expr, limit);
  11813. }
  11814. extern HQL_API IHqlExpression *doInstantEclTransformations(IHqlExpression *qquery, unsigned limit)
  11815. {
  11816. try
  11817. {
  11818. return walkRootInstantEclTransformations(qquery, limit);
  11819. }
  11820. catch (...)
  11821. {
  11822. PrintLog("InstantECL transformations - exception caught");
  11823. }
  11824. return LINK(qquery);
  11825. }
  11826. //==============================================================================================================
  11827. //MAKEValueArray(byte, ByteArray);
  11828. typedef UnsignedArray DepthArray;
  11829. struct TransformTrackingInfo
  11830. {
  11831. public:
  11832. void lock();
  11833. void unlock();
  11834. public:
  11835. transformdepth_t curTransformDepth;
  11836. PointerArray transformStack;
  11837. UnsignedArray transformStackMark;
  11838. DepthArray depthStack;
  11839. };
  11840. static TransformTrackingInfo transformExtraState[NUM_PARALLEL_TRANSFORMS+1];
  11841. static bool isActiveMask[NUM_PARALLEL_TRANSFORMS+1];
  11842. #if NUM_PARALLEL_TRANSFORMS==1
  11843. unsigned threadActiveExtraIndex=1;
  11844. #else
  11845. #ifdef _WIN32
  11846. __declspec(thread) unsigned threadActiveExtraIndex;
  11847. #else
  11848. __thread unsigned threadActiveExtraIndex;
  11849. #endif
  11850. #endif
  11851. unsigned queryCurrentTransformDepth()
  11852. {
  11853. //only valid if called within a transform
  11854. const TransformTrackingInfo * state = &transformExtraState[threadActiveExtraIndex];
  11855. return state->curTransformDepth;
  11856. }
  11857. IInterface * CHqlExpression::queryTransformExtra()
  11858. {
  11859. const TransformTrackingInfo * state = &transformExtraState[threadActiveExtraIndex];
  11860. const transformdepth_t curTransformDepth = state->curTransformDepth;
  11861. const unsigned extraIndex = threadActiveExtraIndex-1;
  11862. #if NUM_PARALLEL_TRANSFORMS == 1
  11863. assertex(extraIndex == 0);
  11864. #endif
  11865. assertex(curTransformDepth);
  11866. if (TRANSFORM_DEPTH(transformDepth[extraIndex]) == curTransformDepth)
  11867. return transformExtra[extraIndex];
  11868. return NULL;
  11869. }
  11870. void CHqlExpression::resetTransformExtra(IInterface * x, unsigned depth)
  11871. {
  11872. const unsigned extraIndex = threadActiveExtraIndex-1;
  11873. #if NUM_PARALLEL_TRANSFORMS == 1
  11874. assertex(extraIndex == 0);
  11875. #endif
  11876. RELEASE_TRANSFORM_EXTRA(transformDepth[extraIndex], transformExtra[extraIndex]);
  11877. transformDepth[extraIndex] = depth;
  11878. transformExtra[extraIndex] = x;
  11879. }
  11880. //The following is extacted from the function definition below. Using a macro because I'm not convinced how well it gets inlined.
  11881. #define DO_SET_TRANSFORM_EXTRA(x, depthMask) \
  11882. { \
  11883. TransformTrackingInfo * state = &transformExtraState[threadActiveExtraIndex]; \
  11884. const transformdepth_t curTransformDepth = state->curTransformDepth; \
  11885. const unsigned extraIndex = threadActiveExtraIndex-1; \
  11886. assertex(curTransformDepth); \
  11887. const transformdepth_t exprDepth = transformDepth[extraIndex]; \
  11888. if (TRANSFORM_DEPTH(exprDepth) == curTransformDepth) \
  11889. { \
  11890. RELEASE_TRANSFORM_EXTRA(exprDepth, transformExtra[extraIndex]); \
  11891. } \
  11892. else \
  11893. { \
  11894. unsigned saveDepth = exprDepth; \
  11895. if (exprDepth) \
  11896. { \
  11897. IInterface * saveValue = transformExtra[extraIndex]; \
  11898. if (saveValue == this) \
  11899. saveDepth |= TRANSFORM_DEPTH_SAVE_MATCH_EXPR; \
  11900. else \
  11901. state->transformStack.append(saveValue); \
  11902. } \
  11903. state->transformStack.append(LINK(this)); \
  11904. if (curTransformDepth > 1) \
  11905. state->depthStack.append(saveDepth); \
  11906. } \
  11907. \
  11908. const transformdepth_t newDepth = (curTransformDepth | depthMask); \
  11909. if (exprDepth != newDepth) \
  11910. transformDepth[extraIndex] = newDepth; \
  11911. transformExtra[extraIndex] = x; \
  11912. }
  11913. void CHqlExpression::doSetTransformExtra(IInterface * x, unsigned depthMask)
  11914. {
  11915. #ifdef GATHER_LINK_STATS
  11916. numSetExtra++;
  11917. if (x == this)
  11918. numSetExtraSame++;
  11919. if (depthMask & TRANSFORM_DEPTH_NOLINK)
  11920. numSetExtraUnlinked++;
  11921. #endif
  11922. TransformTrackingInfo * state = &transformExtraState[threadActiveExtraIndex];
  11923. const transformdepth_t curTransformDepth = state->curTransformDepth;
  11924. const unsigned extraIndex = threadActiveExtraIndex-1;
  11925. #if NUM_PARALLEL_TRANSFORMS == 1
  11926. assertex(extraIndex == 0);
  11927. #endif
  11928. assertex(curTransformDepth);
  11929. const transformdepth_t exprDepth = transformDepth[extraIndex];
  11930. if (TRANSFORM_DEPTH(exprDepth) == curTransformDepth)
  11931. {
  11932. RELEASE_TRANSFORM_EXTRA(exprDepth, transformExtra[extraIndex]);
  11933. }
  11934. else
  11935. {
  11936. #ifdef GATHER_LINK_STATS
  11937. if (curTransformDepth > 1)
  11938. numNestedExtra++;
  11939. #endif
  11940. unsigned saveDepth = exprDepth;
  11941. if (exprDepth)
  11942. {
  11943. IInterface * saveValue = transformExtra[extraIndex];
  11944. if (saveValue == this)
  11945. saveDepth |= TRANSFORM_DEPTH_SAVE_MATCH_EXPR;
  11946. else
  11947. state->transformStack.append(saveValue);
  11948. }
  11949. state->transformStack.append(LINK(this)); // if expr was created inside a transformer, then it may disappear before unlock is called()
  11950. if (curTransformDepth > 1) // don't save depth if it can only be 0
  11951. state->depthStack.append(saveDepth);
  11952. }
  11953. const transformdepth_t newDepth = (curTransformDepth | depthMask);
  11954. if (exprDepth != newDepth)
  11955. transformDepth[extraIndex] = newDepth;
  11956. transformExtra[extraIndex] = x;
  11957. }
  11958. void CHqlExpression::setTransformExtra(IInterface * x)
  11959. {
  11960. unsigned depthMask;
  11961. if (x != this)
  11962. {
  11963. ::Link(x);
  11964. depthMask = 0;
  11965. }
  11966. else
  11967. depthMask = TRANSFORM_DEPTH_NOLINK;
  11968. DO_SET_TRANSFORM_EXTRA(x, depthMask);
  11969. }
  11970. void CHqlExpression::setTransformExtraOwned(IInterface * x)
  11971. {
  11972. DO_SET_TRANSFORM_EXTRA(x, 0);
  11973. }
  11974. void CHqlExpression::setTransformExtraUnlinked(IInterface * x)
  11975. {
  11976. DO_SET_TRANSFORM_EXTRA(x, TRANSFORM_DEPTH_NOLINK);
  11977. }
  11978. void TransformTrackingInfo::lock()
  11979. {
  11980. #ifdef GATHER_LINK_STATS
  11981. numLocks++;
  11982. if (curTransformDepth)
  11983. numNestedLocks++;
  11984. if (curTransformDepth>=maxNestedLocks)
  11985. maxNestedLocks = curTransformDepth+1;
  11986. #endif
  11987. curTransformDepth++;
  11988. assertex((curTransformDepth & TRANSFORM_DEPTH_MASK) != 0); //
  11989. transformStackMark.append(transformStack.ordinality());
  11990. }
  11991. void TransformTrackingInfo::unlock()
  11992. {
  11993. unsigned transformStackLevel = transformStackMark.pop();
  11994. while (transformStack.ordinality() > transformStackLevel)
  11995. {
  11996. CHqlExpression * expr = (CHqlExpression *)transformStack.pop();
  11997. unsigned oldDepth = 0;
  11998. IInterface * extra = NULL;
  11999. if (curTransformDepth > 1)
  12000. {
  12001. oldDepth = depthStack.pop();
  12002. if (oldDepth & TRANSFORM_DEPTH_SAVE_MATCH_EXPR)
  12003. extra = expr;
  12004. else if (oldDepth)
  12005. extra = (IInterface *)transformStack.pop();
  12006. }
  12007. expr->resetTransformExtra(extra, oldDepth);
  12008. expr->Release();
  12009. }
  12010. curTransformDepth--;
  12011. }
  12012. static void ensureThreadExtraIndex()
  12013. {
  12014. {
  12015. CriticalBlock block(*transformCS);
  12016. if (threadActiveExtraIndex != 0)
  12017. return;
  12018. }
  12019. transformSemaphore->wait();
  12020. {
  12021. CriticalBlock block(*transformCS);
  12022. assertex(threadActiveExtraIndex == 0); // something seriously wrong...
  12023. for (unsigned i=1; i <= NUM_PARALLEL_TRANSFORMS; i++)
  12024. {
  12025. if (!isActiveMask[i])
  12026. {
  12027. threadActiveExtraIndex = i;
  12028. isActiveMask[i] = true;
  12029. return;
  12030. }
  12031. }
  12032. throwUnexpected();
  12033. }
  12034. }
  12035. static void releaseExtraIndex()
  12036. {
  12037. CriticalBlock block(*transformCS);
  12038. isActiveMask[threadActiveExtraIndex] = false;
  12039. threadActiveExtraIndex = 0;
  12040. transformSemaphore->signal();
  12041. }
  12042. extern HQL_API void lockTransformMutex()
  12043. {
  12044. #if NUM_PARALLEL_TRANSFORMS==1
  12045. assertex(transformMutex);
  12046. transformMutex->lock();
  12047. #else
  12048. assertex(transformCS);
  12049. ensureThreadExtraIndex();
  12050. #endif
  12051. transformExtraState[threadActiveExtraIndex].lock();
  12052. }
  12053. extern HQL_API void unlockTransformMutex()
  12054. {
  12055. assertex(threadActiveExtraIndex);
  12056. TransformTrackingInfo * state = &transformExtraState[threadActiveExtraIndex];
  12057. state->unlock();
  12058. #if NUM_PARALLEL_TRANSFORMS==1
  12059. transformMutex->unlock();
  12060. #else
  12061. if (state->curTransformDepth == 0)
  12062. releaseExtraIndex();
  12063. #endif
  12064. }
  12065. //==============================================================================================================
  12066. unsigned getExpressionCRC(IHqlExpression * expr)
  12067. {
  12068. CriticalBlock procedure(*crcCS);
  12069. return expr->getCachedEclCRC();
  12070. }
  12071. // ================ improve error message ======================
  12072. HQL_API StringBuffer& getFriendlyTypeStr(IHqlExpression* e, StringBuffer& s)
  12073. {
  12074. assertex(e);
  12075. ITypeInfo *type = e->queryType();
  12076. return getFriendlyTypeStr(type,s);
  12077. }
  12078. HQL_API StringBuffer& getFriendlyTypeStr(ITypeInfo* type, StringBuffer& s)
  12079. {
  12080. if (!type)
  12081. return s.append("<unknown>");
  12082. switch(type->getTypeCode())
  12083. {
  12084. case type_int:
  12085. s.append("Integer");
  12086. break;
  12087. case type_real:
  12088. s.append("Real");
  12089. break;
  12090. case type_boolean:
  12091. s.append("Boolean");
  12092. break;
  12093. case type_string:
  12094. s.append("String");
  12095. break;
  12096. case type_data:
  12097. s.append("Data");
  12098. break;
  12099. case type_set:
  12100. {
  12101. s.append("Set of ");
  12102. ITypeInfo* chdType = type->queryChildType();
  12103. getFriendlyTypeStr(chdType, s);
  12104. break;
  12105. }
  12106. case type_groupedtable:
  12107. {
  12108. s.append("Grouped ");
  12109. ITypeInfo* chdType = type->queryChildType();
  12110. if (chdType)
  12111. getFriendlyTypeStr(chdType, s);
  12112. else
  12113. s.append("Table");
  12114. break;
  12115. }
  12116. case type_table:
  12117. {
  12118. s.append("Table of ");
  12119. ITypeInfo * chdType = queryRecordType(type);
  12120. if (chdType)
  12121. {
  12122. if (!queryOriginalName(chdType, s))
  12123. chdType->getECLType(s);
  12124. }
  12125. else
  12126. s.append("<unknown>");
  12127. break;
  12128. }
  12129. case type_dictionary:
  12130. {
  12131. s.append(type->queryTypeName()).append(" of ");
  12132. ITypeInfo * chdType = queryRecordType(type);
  12133. if (chdType)
  12134. {
  12135. if (!queryOriginalName(chdType, s))
  12136. chdType->getECLType(s);
  12137. }
  12138. else
  12139. s.append("<unknown>");
  12140. break;
  12141. }
  12142. case type_record:
  12143. s.append("Record ");
  12144. if (!queryOriginalName(type, s))
  12145. type->getECLType(s);
  12146. break;
  12147. case type_transform:
  12148. s.append("Transform ");
  12149. if (!queryOriginalName(type, s))
  12150. type->getECLType(s);
  12151. break;
  12152. case type_row:
  12153. {
  12154. s.append("row");
  12155. ITypeInfo * childType = type->queryChildType();
  12156. if (childType)
  12157. {
  12158. s.append(" of ");
  12159. if (!queryOriginalName(type, s) && !queryOriginalName(childType, s))
  12160. childType->getECLType(s);
  12161. }
  12162. break;
  12163. }
  12164. case type_void:
  12165. s.append("<void>");
  12166. break;
  12167. default:
  12168. type->getECLType(s);
  12169. }
  12170. return s;
  12171. }
  12172. //==============================================================================================================
  12173. static HqlTransformerInfo virtualAttributeRemoverInfo("VirtualAttributeRemover");
  12174. class VirtualAttributeRemover : public QuickHqlTransformer
  12175. {
  12176. public:
  12177. VirtualAttributeRemover() : QuickHqlTransformer(virtualAttributeRemoverInfo, NULL) {}
  12178. virtual IHqlExpression * createTransformed(IHqlExpression * expr)
  12179. {
  12180. switch (expr->getOperator())
  12181. {
  12182. case no_field:
  12183. {
  12184. if (expr->hasAttribute(virtualAtom))
  12185. {
  12186. OwnedHqlExpr cleaned = removeAttribute(expr, virtualAtom);
  12187. return QuickHqlTransformer::createTransformed(cleaned);
  12188. }
  12189. break;
  12190. }
  12191. }
  12192. return QuickHqlTransformer::createTransformed(expr);
  12193. }
  12194. };
  12195. static bool removeVirtualAttributes(HqlExprArray & fields, IHqlExpression * cur, HqlMapTransformer & transformer)
  12196. {
  12197. switch (cur->getOperator())
  12198. {
  12199. case no_field:
  12200. {
  12201. ITypeInfo * type = cur->queryType();
  12202. Linked<ITypeInfo> targetType = type;
  12203. switch (type->getTypeCode())
  12204. {
  12205. case type_groupedtable:
  12206. case type_table:
  12207. case type_row:
  12208. {
  12209. IHqlExpression * fieldRecord = cur->queryRecord();
  12210. HqlExprArray subFields;
  12211. if (removeVirtualAttributes(subFields, fieldRecord, transformer))
  12212. {
  12213. OwnedHqlExpr newRecord = fieldRecord->clone(subFields);
  12214. switch (type->getTypeCode())
  12215. {
  12216. case type_groupedtable:
  12217. targetType.setown(makeGroupedTableType(makeTableType(makeRowType(newRecord->getType()))));
  12218. break;
  12219. case type_table:
  12220. targetType.setown(makeTableType(makeRowType(newRecord->getType())));
  12221. break;
  12222. case type_row:
  12223. targetType.set(makeRowType(newRecord->queryType()));
  12224. break;
  12225. case type_record:
  12226. throwUnexpected();
  12227. break;
  12228. }
  12229. }
  12230. break;
  12231. }
  12232. }
  12233. LinkedHqlExpr newField = cur;
  12234. if ((type != targetType) || cur->hasAttribute(virtualAtom))
  12235. {
  12236. HqlExprArray args;
  12237. unwindChildren(args, cur);
  12238. removeAttribute(args, virtualAtom);
  12239. newField.setown(createField(cur->queryId(), targetType.getLink(), args));
  12240. }
  12241. fields.append(*LINK(newField));
  12242. transformer.setMapping(cur, newField);
  12243. return (newField != cur);
  12244. }
  12245. case no_ifblock:
  12246. {
  12247. HqlExprArray subfields;
  12248. IHqlExpression * condition = cur->queryChild(0);
  12249. OwnedHqlExpr mappedCondition = transformer.transformRoot(condition);
  12250. if (removeVirtualAttributes(subfields, cur->queryChild(1), transformer) || (condition != mappedCondition))
  12251. {
  12252. fields.append(*createValue(no_ifblock, makeNullType(), LINK(mappedCondition), createRecord(subfields)));
  12253. return true;
  12254. }
  12255. fields.append(*LINK(cur));
  12256. return false;
  12257. }
  12258. case no_record:
  12259. {
  12260. bool changed = false;
  12261. ForEachChild(idx, cur)
  12262. if (removeVirtualAttributes(fields, cur->queryChild(idx), transformer))
  12263. changed = true;
  12264. return changed;
  12265. }
  12266. case no_attr:
  12267. case no_attr_expr:
  12268. case no_attr_link:
  12269. fields.append(*LINK(cur));
  12270. return false;
  12271. }
  12272. UNIMPLEMENTED;
  12273. }
  12274. IHqlExpression * removeVirtualAttributes(IHqlExpression * record)
  12275. {
  12276. assertex(record->getOperator() == no_record);
  12277. VirtualAttributeRemover transformer;
  12278. return transformer.transform(record);
  12279. }
  12280. IHqlExpression * extractChildren(IHqlExpression * value)
  12281. {
  12282. HqlExprArray children;
  12283. unwindChildren(children, value);
  12284. return createComma(children);
  12285. }
  12286. IHqlExpression * queryDatasetCursor(IHqlExpression * ds)
  12287. {
  12288. while ((ds->getOperator() == no_select) && !ds->isDataset() && !ds->isDictionary())
  12289. ds = ds->queryChild(0);
  12290. return ds;
  12291. }
  12292. IHqlExpression * querySelectorDataset(IHqlExpression * expr, bool & isNew)
  12293. {
  12294. assertex(expr->getOperator() == no_select);
  12295. isNew = expr->hasAttribute(newAtom);
  12296. IHqlExpression * ds = expr->queryChild(0);
  12297. while ((ds->getOperator() == no_select) && !ds->isDataset() && !ds->isDictionary())
  12298. {
  12299. if (ds->hasAttribute(newAtom))
  12300. isNew = true;
  12301. assertex(ds->isDatarow());
  12302. ds = ds->queryChild(0);
  12303. }
  12304. return ds;
  12305. }
  12306. bool isNewSelector(IHqlExpression * expr)
  12307. {
  12308. assertex(expr->getOperator() == no_select);
  12309. if (expr->hasAttribute(newAtom))
  12310. return true;
  12311. IHqlExpression * ds = expr->queryChild(0);
  12312. while ((ds->getOperator() == no_select) && !ds->isDataset() && !ds->isDictionary())
  12313. {
  12314. if (ds->hasAttribute(newAtom))
  12315. return true;
  12316. assertex(ds->isDatarow());
  12317. ds = ds->queryChild(0);
  12318. }
  12319. return false;
  12320. }
  12321. bool isTargetSelector(IHqlExpression * expr)
  12322. {
  12323. while (expr->getOperator() == no_select)
  12324. expr = expr->queryChild(0);
  12325. return (expr->getOperator() == no_self);
  12326. }
  12327. IHqlExpression * replaceSelectorDataset(IHqlExpression * expr, IHqlExpression * newDataset)
  12328. {
  12329. assertex(expr->getOperator() == no_select);
  12330. IHqlExpression * ds = expr->queryChild(0);
  12331. if ((ds->getOperator() == no_select) && !ds->isDataset() && !ds->isDictionary())
  12332. {
  12333. OwnedHqlExpr newSelector = replaceSelectorDataset(ds, newDataset);
  12334. return replaceChild(expr, 0, newSelector);
  12335. }
  12336. else
  12337. return replaceChild(expr, 0, newDataset);
  12338. }
  12339. IHqlExpression * querySkipDatasetMeta(IHqlExpression * dataset)
  12340. {
  12341. loop
  12342. {
  12343. switch (dataset->getOperator())
  12344. {
  12345. case no_sorted:
  12346. case no_grouped:
  12347. case no_distributed:
  12348. case no_preservemeta:
  12349. case no_stepped:
  12350. break;
  12351. default:
  12352. return dataset;
  12353. }
  12354. dataset = dataset->queryChild(0);
  12355. }
  12356. }
  12357. //==============================================================================================================
  12358. static ITypeInfo * doGetSimplifiedType(ITypeInfo * type, bool isConditional, bool isSerialized, IAtom * serialForm)
  12359. {
  12360. ITypeInfo * promoted = type->queryPromotedType();
  12361. switch (type->getTypeCode())
  12362. {
  12363. case type_boolean:
  12364. case type_int:
  12365. case type_real:
  12366. case type_decimal:
  12367. case type_swapint:
  12368. case type_packedint:
  12369. return LINK(type);
  12370. case type_data:
  12371. case type_string:
  12372. case type_varstring:
  12373. case type_unicode:
  12374. case type_varunicode:
  12375. case type_utf8:
  12376. case type_qstring:
  12377. if (isConditional)
  12378. return getStretchedType(UNKNOWN_LENGTH, type);
  12379. return LINK(promoted);
  12380. case type_date:
  12381. case type_enumerated:
  12382. return makeIntType(promoted->getSize(), false);
  12383. case type_bitfield:
  12384. return LINK(promoted);
  12385. case type_alien:
  12386. return getSimplifiedType(promoted, isConditional, isSerialized, serialForm);
  12387. case type_row:
  12388. case type_dictionary:
  12389. case type_table:
  12390. case type_groupedtable:
  12391. case type_transform:
  12392. if (isSerialized)
  12393. return getSerializedForm(type, serialForm);
  12394. //should possibly remove some weird options
  12395. return LINK(type);
  12396. case type_set:
  12397. {
  12398. ITypeInfo * childType = type->queryChildType();
  12399. Owned<ITypeInfo> simpleChildType = getSimplifiedType(childType, false, isSerialized, serialForm);
  12400. return makeSetType(simpleChildType.getClear());
  12401. }
  12402. }
  12403. UNIMPLEMENTED; //i.e. doesn't make any sense....
  12404. }
  12405. ITypeInfo * getSimplifiedType(ITypeInfo * type, bool isConditional, bool isSerialized, IAtom * serialForm)
  12406. {
  12407. Owned<ITypeInfo> newType = doGetSimplifiedType(type, isConditional, isSerialized, serialForm);
  12408. if (isSameBasicType(newType, type))
  12409. return LINK(type);
  12410. newType.setown(cloneModifiers(type, newType));
  12411. //add a maxlength qualifier, and preserve any maxlength qualifiers in the source.
  12412. return newType.getClear();
  12413. }
  12414. static void simplifyFileViewRecordTypes(HqlExprArray & fields, IHqlExpression * cur, bool isConditional, bool & needsTransform, bool isKey, unsigned & count)
  12415. {
  12416. switch (cur->getOperator())
  12417. {
  12418. case no_field:
  12419. {
  12420. bool forceSimplify = false;
  12421. if (isKey)
  12422. {
  12423. if (cur->hasAttribute(blobAtom))
  12424. forceSimplify = true;
  12425. }
  12426. else
  12427. {
  12428. //MORE: Really not so sure about this...
  12429. if (cur->hasAttribute(virtualAtom))
  12430. return;
  12431. }
  12432. ITypeInfo * type = cur->queryType();
  12433. Owned<ITypeInfo> targetType;
  12434. HqlExprArray attrs;
  12435. switch (type->getTypeCode())
  12436. {
  12437. case type_groupedtable:
  12438. throwError(HQLERR_NoBrowseGroupChild);
  12439. case type_table:
  12440. {
  12441. bool childNeedsTransform = false;
  12442. IHqlExpression * fieldRecord = cur->queryRecord();
  12443. HqlExprArray subFields;
  12444. simplifyFileViewRecordTypes(subFields, fieldRecord, isConditional, childNeedsTransform, isKey, count);
  12445. if (childNeedsTransform || hasLinkCountedModifier(type))
  12446. {
  12447. OwnedHqlExpr newRecord = fieldRecord->clone(subFields);
  12448. targetType.setown(makeTableType(makeRowType(newRecord->getType())));
  12449. }
  12450. else
  12451. targetType.set(type);
  12452. IHqlExpression * maxCountAttr = cur->queryAttribute(maxCountAtom);
  12453. IHqlExpression * countAttr = cur->queryAttribute(countAtom);
  12454. if (countAttr || cur->hasAttribute(sizeofAtom))
  12455. forceSimplify = true;
  12456. if (maxCountAttr)
  12457. attrs.append(*LINK(maxCountAttr));
  12458. if (countAttr && !maxCountAttr && countAttr->queryChild(0)->queryValue())
  12459. attrs.append(*createAttribute(maxCountAtom, LINK(countAttr->queryChild(0))));
  12460. break;
  12461. }
  12462. case type_set:
  12463. targetType.setown(getSimplifiedType(type, false, true, diskAtom));
  12464. break;
  12465. case type_row:
  12466. {
  12467. bool childNeedsTransform = false;
  12468. IHqlExpression * fieldRecord = cur->queryRecord();
  12469. HqlExprArray subFields;
  12470. simplifyFileViewRecordTypes(subFields, fieldRecord, isConditional, childNeedsTransform, isKey, count);
  12471. if (childNeedsTransform)
  12472. {
  12473. OwnedHqlExpr newRecord = fieldRecord->clone(subFields);
  12474. targetType.setown(replaceChildType(type, newRecord->queryType()));
  12475. }
  12476. else
  12477. targetType.set(type);
  12478. break;
  12479. }
  12480. return;
  12481. default:
  12482. targetType.setown(getSimplifiedType(type, isConditional, true, diskAtom));
  12483. break;
  12484. }
  12485. LinkedHqlExpr newField = cur;
  12486. if (forceSimplify || type != targetType)
  12487. {
  12488. needsTransform = true;
  12489. //MORE xmldefault, default
  12490. inheritAttribute(attrs, cur, xpathAtom);
  12491. inheritAttribute(attrs, cur, xmlDefaultAtom);
  12492. inheritAttribute(attrs, cur, defaultAtom);
  12493. newField.setown(createField(cur->queryId(), targetType.getLink(), attrs));
  12494. }
  12495. fields.append(*LINK(newField));
  12496. break;
  12497. }
  12498. case no_ifblock:
  12499. {
  12500. //Remove them for the moment...
  12501. //Gets complicated if they are kept, because the test condition will need testing
  12502. needsTransform = true;
  12503. HqlExprArray subfields;
  12504. StringBuffer name;
  12505. name.append("unnamed").append(++count);
  12506. subfields.append(*createField(createIdAtom(name), makeBoolType(), NULL, createAttribute(__ifblockAtom)));
  12507. simplifyFileViewRecordTypes(subfields, cur->queryChild(1), true, needsTransform, isKey, count);
  12508. // fields.append(*createValue(no_ifblock, makeVoidType(), createValue(no_not, makeBoolType(), createConstant(false)), createRecord(subfields)));
  12509. fields.append(*createValue(no_ifblock, makeNullType(), createConstant(true), createRecord(subfields)));
  12510. break;
  12511. }
  12512. case no_record:
  12513. {
  12514. ForEachChild(idx, cur)
  12515. {
  12516. IHqlExpression * next = cur->queryChild(idx);
  12517. if (next->getOperator() == no_record)
  12518. {
  12519. HqlExprArray subfields;
  12520. simplifyFileViewRecordTypes(subfields, next, isConditional, needsTransform, isKey, count);
  12521. fields.append(*cloneOrLink(cur, subfields));
  12522. }
  12523. else
  12524. simplifyFileViewRecordTypes(fields, next, isConditional, needsTransform, isKey, count);
  12525. }
  12526. break;
  12527. }
  12528. case no_attr:
  12529. case no_attr_expr:
  12530. case no_attr_link:
  12531. fields.append(*LINK(cur));
  12532. break;
  12533. }
  12534. }
  12535. static IHqlExpression * simplifyFileViewRecordTypes(IHqlExpression * record, bool & needsTransform, bool isKey)
  12536. {
  12537. assertex(record->getOperator() == no_record);
  12538. HqlExprArray fields;
  12539. unsigned count = 0;
  12540. simplifyFileViewRecordTypes(fields, record, false, needsTransform, isKey, count);
  12541. return cloneOrLink(record, fields);
  12542. }
  12543. extern HQL_API IHqlExpression * getFileViewerRecord(IHqlExpression * record, bool isKey)
  12544. {
  12545. bool needsTransform = false;
  12546. try
  12547. {
  12548. OwnedHqlExpr newRecord = simplifyFileViewRecordTypes(record, needsTransform, isKey);
  12549. if (needsTransform)
  12550. return newRecord.getClear();
  12551. return NULL;
  12552. }
  12553. catch (IException * e)
  12554. {
  12555. LOG(MCwarning, unknownJob, e);
  12556. e->Release();
  12557. }
  12558. return NULL;
  12559. }
  12560. static void getSimplifiedAssigns(HqlExprArray & assigns, IHqlExpression * tgt, IHqlExpression * src, IHqlExpression * targetSelector, IHqlExpression * sourceSelector, unsigned targetDelta)
  12561. {
  12562. switch (src->getOperator())
  12563. {
  12564. case no_field:
  12565. {
  12566. //MORE: Really not so sure about this...
  12567. if (src->hasAttribute(virtualAtom) || src->hasAttribute(__ifblockAtom))
  12568. return;
  12569. OwnedHqlExpr srcSelect = sourceSelector ? createSelectExpr(LINK(sourceSelector), LINK(src)) : LINK(src);
  12570. OwnedHqlExpr tgtSelect = createSelectExpr(LINK(targetSelector), LINK(tgt));
  12571. ITypeInfo * type = src->queryType();
  12572. type_t tc = type->getTypeCode();
  12573. if (tc == type_row)
  12574. {
  12575. IHqlExpression * srcRecord = src->queryRecord();
  12576. if (false && isSimplifiedRecord(srcRecord, false))
  12577. assigns.append(*createAssign(LINK(tgtSelect), LINK(srcSelect)));
  12578. else
  12579. {
  12580. OwnedHqlExpr seq = createSelectorSequence();
  12581. OwnedHqlExpr leftChildSelector = createSelector(no_left, srcSelect, seq);
  12582. OwnedHqlExpr tform = getSimplifiedTransform(tgt->queryRecord(), src->queryRecord(), leftChildSelector);
  12583. OwnedHqlExpr pj = createRow(no_projectrow, LINK(srcSelect), createComma(tform.getClear(), LINK(seq)));
  12584. assigns.append(*createAssign(LINK(tgtSelect), LINK(pj)));
  12585. }
  12586. }
  12587. else if (((tc == type_table) || (tc == type_groupedtable)) && (srcSelect->queryType() != tgtSelect->queryType()))
  12588. {
  12589. //self.target := project(srcSelect, transform(...));
  12590. IHqlExpression * srcRecord = src->queryRecord();
  12591. OwnedHqlExpr seq = createSelectorSequence();
  12592. OwnedHqlExpr srcSelector = createSelector(no_left, srcSelect, seq);
  12593. OwnedHqlExpr transform = getSimplifiedTransform(tgt->queryRecord(), srcRecord, srcSelector);
  12594. OwnedHqlExpr project = createDataset(no_hqlproject, LINK(srcSelect), createComma(LINK(transform), LINK(seq)));
  12595. assigns.append(*createAssign(LINK(tgtSelect), LINK(project)));
  12596. }
  12597. else
  12598. assigns.append(*createAssign(LINK(tgtSelect), LINK(srcSelect)));
  12599. break;
  12600. }
  12601. case no_ifblock:
  12602. {
  12603. IHqlExpression * specialField = tgt->queryChild(1)->queryChild(0);
  12604. OwnedHqlExpr tgtSelect = createSelectExpr(LINK(targetSelector), LINK(tgt));
  12605. IHqlExpression * self = querySelfReference();
  12606. OwnedHqlExpr cond = replaceSelector(src->queryChild(0), self, sourceSelector);
  12607. assigns.append(*createAssign(createSelectExpr(LINK(targetSelector), LINK(specialField)), cond.getClear()));
  12608. getSimplifiedAssigns(assigns, tgt->queryChild(1), src->queryChild(1), targetSelector, sourceSelector, 1);
  12609. break;
  12610. }
  12611. case no_record:
  12612. {
  12613. ForEachChild(idx, src)
  12614. getSimplifiedAssigns(assigns, tgt->queryChild(idx+targetDelta), src->queryChild(idx), targetSelector, sourceSelector, 0);
  12615. break;
  12616. }
  12617. case no_attr:
  12618. case no_attr_expr:
  12619. case no_attr_link:
  12620. break;
  12621. default:
  12622. UNIMPLEMENTED;
  12623. }
  12624. }
  12625. extern HQL_API IHqlExpression * getSimplifiedTransform(IHqlExpression * tgt, IHqlExpression * src, IHqlExpression * sourceSelector)
  12626. {
  12627. HqlExprArray assigns;
  12628. OwnedHqlExpr self = getSelf(tgt);
  12629. getSimplifiedAssigns(assigns, tgt, src, self, sourceSelector, 0);
  12630. return createValue(no_newtransform, makeTransformType(tgt->getType()), assigns);
  12631. }
  12632. extern HQL_API bool isSimplifiedRecord(IHqlExpression * expr, bool isKey)
  12633. {
  12634. OwnedHqlExpr simplified = getFileViewerRecord(expr, isKey);
  12635. return !simplified || (expr == simplified);
  12636. }
  12637. void unwindChildren(HqlExprArray & children, IHqlExpression * expr)
  12638. {
  12639. unsigned max = expr->numChildren();
  12640. children.ensure(max);
  12641. for (unsigned idx=0; idx < max; idx++)
  12642. {
  12643. IHqlExpression * child = expr->queryChild(idx);
  12644. children.append(*LINK(child));
  12645. }
  12646. }
  12647. void unwindChildren(HqlExprArray & children, const IHqlExpression * expr, unsigned first)
  12648. {
  12649. unsigned max = expr->numChildren();
  12650. children.ensure(max-first);
  12651. for (unsigned idx=first; idx < max; idx++)
  12652. {
  12653. IHqlExpression * child = expr->queryChild(idx);
  12654. children.append(*LINK(child));
  12655. }
  12656. }
  12657. void unwindChildren(HqlExprArray & children, const IHqlExpression * expr, unsigned first, unsigned max)
  12658. {
  12659. children.ensure(max-first);
  12660. for (unsigned idx=first; idx < max; idx++)
  12661. {
  12662. IHqlExpression * child = expr->queryChild(idx);
  12663. children.append(*LINK(child));
  12664. }
  12665. }
  12666. void unwindChildren(HqlExprCopyArray & children, const IHqlExpression * expr, unsigned first)
  12667. {
  12668. unsigned max = expr->numChildren();
  12669. children.ensure(max-first);
  12670. for (unsigned idx=first; idx < max; idx++)
  12671. {
  12672. IHqlExpression * child = expr->queryChild(idx);
  12673. children.append(*child);
  12674. }
  12675. }
  12676. void unwindRealChildren(HqlExprArray & children, const IHqlExpression * expr, unsigned first)
  12677. {
  12678. unsigned max = expr->numChildren();
  12679. children.ensure(max-first);
  12680. for (unsigned idx=first; idx < max; idx++)
  12681. {
  12682. IHqlExpression * child = expr->queryChild(idx);
  12683. if (!child->isAttribute())
  12684. children.append(*LINK(child));
  12685. }
  12686. }
  12687. void unwindAttributes(HqlExprArray & children, const IHqlExpression * expr)
  12688. {
  12689. unsigned max = expr->numChildren();
  12690. for (unsigned idx=0; idx < max; idx++)
  12691. {
  12692. IHqlExpression * child = expr->queryChild(idx);
  12693. if (child->isAttribute())
  12694. {
  12695. //Subsequent calls to ensure are quick no-ops
  12696. children.ensure(max - idx);
  12697. children.append(*LINK(child));
  12698. }
  12699. }
  12700. }
  12701. void unwindList(HqlExprArray &dst, IHqlExpression * expr, node_operator op)
  12702. {
  12703. while (expr->getOperator() == op)
  12704. {
  12705. unsigned _max = expr->numChildren();
  12706. if (_max == 0)
  12707. return;
  12708. unsigned max = _max-1;
  12709. for (unsigned i=0; i < max; i++)
  12710. unwindList(dst, expr->queryChild(i), op);
  12711. expr = expr->queryChild(max);
  12712. }
  12713. dst.append(*LINK(expr));
  12714. }
  12715. void unwindCopyList(HqlExprCopyArray &dst, IHqlExpression * expr, node_operator op)
  12716. {
  12717. while (expr->getOperator() == op)
  12718. {
  12719. unsigned _max = expr->numChildren();
  12720. if (_max == 0)
  12721. return;
  12722. unsigned max = _max-1;
  12723. for (unsigned i=0; i < max; i++)
  12724. unwindCopyList(dst, expr->queryChild(i), op);
  12725. expr = expr->queryChild(max);
  12726. }
  12727. dst.append(*expr);
  12728. }
  12729. void unwindCommaCompound(HqlExprArray & target, IHqlExpression * expr)
  12730. {
  12731. switch (expr->getOperator())
  12732. {
  12733. case no_compound:
  12734. case no_comma:
  12735. case no_actionlist:
  12736. {
  12737. ForEachChild(idx, expr)
  12738. unwindCommaCompound(target, expr->queryChild(idx));
  12739. break;
  12740. }
  12741. default:
  12742. target.append(*LINK(expr));
  12743. break;
  12744. }
  12745. }
  12746. void unwindRecordAsSelects(HqlExprArray & children, IHqlExpression * record, IHqlExpression * ds, unsigned limit)
  12747. {
  12748. ForEachChild(idx, record)
  12749. {
  12750. if (idx == limit)
  12751. return;
  12752. IHqlExpression * cur = record->queryChild(idx);
  12753. switch (cur->getOperator())
  12754. {
  12755. case no_field:
  12756. {
  12757. OwnedHqlExpr selected = createSelectExpr(LINK(ds), LINK(cur));
  12758. IHqlExpression * fieldRecord = cur->queryRecord();
  12759. if (fieldRecord && !cur->isDataset())
  12760. unwindRecordAsSelects(children, fieldRecord, selected);
  12761. else
  12762. children.append(*selected.getClear());
  12763. break;
  12764. }
  12765. case no_ifblock:
  12766. unwindRecordAsSelects(children, cur->queryChild(1), ds);
  12767. break;
  12768. case no_record:
  12769. unwindRecordAsSelects(children, cur, ds);
  12770. break;
  12771. case no_attr:
  12772. case no_attr_link:
  12773. case no_attr_expr:
  12774. break;
  12775. default:
  12776. UNIMPLEMENTED;
  12777. }
  12778. }
  12779. }
  12780. void unwindAttribute(HqlExprArray & args, IHqlExpression * expr, IAtom * name)
  12781. {
  12782. IHqlExpression * attr = expr->queryAttribute(name);
  12783. if (attr)
  12784. args.append(*LINK(attr));
  12785. }
  12786. unsigned unwoundCount(IHqlExpression * expr, node_operator op)
  12787. {
  12788. if (!expr)
  12789. return 0;
  12790. unsigned count = 0;
  12791. // comma almost always needs head recursion
  12792. loop
  12793. {
  12794. if (expr->getOperator() != op)
  12795. return count+1;
  12796. ForEachChildFrom(idx, expr, 1)
  12797. count += unwoundCount(expr->queryChild(idx), op);
  12798. expr = expr->queryChild(0);
  12799. }
  12800. }
  12801. IHqlExpression * queryChildOperator(node_operator op, IHqlExpression * expr)
  12802. {
  12803. ForEachChild(idx, expr)
  12804. {
  12805. IHqlExpression * cur = expr->queryChild(idx);
  12806. if (cur->getOperator() == op)
  12807. return cur;
  12808. }
  12809. return NULL;
  12810. }
  12811. bool isKeyedJoin(IHqlExpression * expr)
  12812. {
  12813. node_operator op = expr->getOperator();
  12814. if ((op == no_join) || (op == no_joincount) || (op == no_denormalize) || (op == no_denormalizegroup))
  12815. {
  12816. if (expr->hasAttribute(allAtom) || expr->hasAttribute(lookupAtom) || expr->hasAttribute(smartAtom))
  12817. return false;
  12818. if (expr->hasAttribute(keyedAtom) || containsAssertKeyed(expr->queryChild(2)))
  12819. return true;
  12820. //Keyed joins only support INNER/LEFT. Default to a normal join for other join types.
  12821. if (!isInnerJoin(expr) && !isLeftJoin(expr))
  12822. return false;
  12823. if (isKey(expr->queryChild(1)))
  12824. return true;
  12825. }
  12826. return false;
  12827. }
  12828. static bool cachedJoinSortOrdersMatch(IHqlExpression * left, IHqlExpression * right);
  12829. static bool doJoinSortOrdersMatch(IHqlExpression * left, IHqlExpression * right)
  12830. {
  12831. node_operator leftOp = left->getOperator();
  12832. node_operator rightOp = right->getOperator();
  12833. if (leftOp != rightOp)
  12834. {
  12835. if (((leftOp == no_left) && (rightOp == no_right)) || ((leftOp == no_right) && (rightOp == no_left)))
  12836. return true;
  12837. return false;
  12838. }
  12839. if (left == right)
  12840. return true;
  12841. if (leftOp == no_field)
  12842. return false;
  12843. unsigned numLeft = left->numChildren();
  12844. unsigned numRight = right->numChildren();
  12845. if (numLeft != numRight)
  12846. return false;
  12847. if ((numLeft == 0) && (left != right))
  12848. return false;
  12849. for (unsigned idx=0; idx<numLeft; idx++)
  12850. if (!cachedJoinSortOrdersMatch(left->queryChild(idx), right->queryChild(idx)))
  12851. return false;
  12852. return true;
  12853. }
  12854. static bool cachedJoinSortOrdersMatch(IHqlExpression * left, IHqlExpression * right)
  12855. {
  12856. IHqlExpression * matched = static_cast<IHqlExpression *>(left->queryTransformExtra());
  12857. if (matched)
  12858. return matched == right;
  12859. bool ret = doJoinSortOrdersMatch(left, right);
  12860. if (ret)
  12861. left->setTransformExtra(right);
  12862. return ret;
  12863. }
  12864. static bool joinSortOrdersMatch(IHqlExpression * left, IHqlExpression * right)
  12865. {
  12866. TransformMutexBlock block;
  12867. return cachedJoinSortOrdersMatch(left, right);
  12868. }
  12869. static bool joinSortOrdersMatch(IHqlExpression * expr)
  12870. {
  12871. switch (expr->getOperator())
  12872. {
  12873. case no_and:
  12874. return joinSortOrdersMatch(expr->queryChild(0)) && joinSortOrdersMatch(expr->queryChild(1));
  12875. case no_eq:
  12876. return joinSortOrdersMatch(expr->queryChild(0), expr->queryChild(1));
  12877. }
  12878. return true;
  12879. }
  12880. bool isSelfJoin(IHqlExpression * expr)
  12881. {
  12882. if (expr->getOperator() != no_join)
  12883. return false;
  12884. IHqlExpression * datasetL = expr->queryChild(0);
  12885. IHqlExpression * datasetR = expr->queryChild(1);
  12886. if (datasetL->queryBody() != datasetR->queryBody())
  12887. return false;
  12888. if (expr->hasAttribute(allAtom) || expr->hasAttribute(lookupAtom) || expr->hasAttribute(smartAtom))
  12889. return false;
  12890. if (expr->queryChild(2)->isConstant())
  12891. return false;
  12892. if (!joinSortOrdersMatch(expr->queryChild(2)))
  12893. return false;
  12894. //Check this isn't going to generate a between join - if it is that takes precedence. A bit arbitrary
  12895. //when one is more efficient.
  12896. JoinSortInfo joinInfo;
  12897. joinInfo.findJoinSortOrders(expr, true);
  12898. if ((joinInfo.slidingMatches.ordinality() != 0) && (joinInfo.queryLeftReq().ordinality() == joinInfo.slidingMatches.ordinality()))
  12899. return false;
  12900. return true;
  12901. }
  12902. IHqlExpression * queryJoinRhs(IHqlExpression * expr)
  12903. {
  12904. if (expr->getOperator() == no_selfjoin)
  12905. return expr->queryChild(0);
  12906. return expr->queryChild(1);
  12907. }
  12908. bool isInnerJoin(IHqlExpression * expr)
  12909. {
  12910. return queryJoinKind(expr) == innerAtom;
  12911. }
  12912. IAtom * queryJoinKind(IHqlExpression * expr)
  12913. {
  12914. unsigned max = expr->numChildren();
  12915. for (unsigned i=4; i < max; i++)
  12916. {
  12917. IHqlExpression * cur = expr->queryChild(i);
  12918. switch (cur->getOperator())
  12919. {
  12920. case no_attr:
  12921. case no_attr_link:
  12922. case no_attr_expr:
  12923. {
  12924. IAtom * name = cur->queryName();
  12925. //Only allow inner joins
  12926. if ((name == innerAtom) || (name == leftouterAtom) || (name == rightouterAtom) ||
  12927. (name == fullouterAtom) || (name == leftonlyAtom) ||
  12928. (name == rightonlyAtom) || (name == fullonlyAtom))
  12929. return name;
  12930. break;
  12931. }
  12932. }
  12933. }
  12934. return innerAtom;
  12935. }
  12936. bool isFullJoin(IHqlExpression * expr)
  12937. {
  12938. return expr->hasAttribute(fullouterAtom) || expr->hasAttribute(fullonlyAtom);
  12939. }
  12940. bool isLeftJoin(IHqlExpression * expr)
  12941. {
  12942. return expr->hasAttribute(leftouterAtom) || expr->hasAttribute(leftonlyAtom);
  12943. }
  12944. bool isRightJoin(IHqlExpression * expr)
  12945. {
  12946. return expr->hasAttribute(rightouterAtom) || expr->hasAttribute(rightonlyAtom);
  12947. }
  12948. bool isSimpleInnerJoin(IHqlExpression * expr)
  12949. {
  12950. return isInnerJoin(expr) && !isLimitedJoin(expr);
  12951. }
  12952. bool isLimitedJoin(IHqlExpression * expr)
  12953. {
  12954. return expr->hasAttribute(keepAtom) || expr->hasAttribute(rowLimitAtom) || expr->hasAttribute(atmostAtom);
  12955. }
  12956. bool filterIsKeyed(IHqlExpression * expr)
  12957. {
  12958. unsigned max = expr->numChildren();
  12959. for (unsigned i=1; i < max; i++)
  12960. if (containsAssertKeyed(expr->queryChild(i)))
  12961. return true;
  12962. return false;
  12963. }
  12964. bool filterIsUnkeyed(IHqlExpression * expr)
  12965. {
  12966. unsigned max = expr->numChildren();
  12967. for (unsigned i=1; i < max; i++)
  12968. if (!containsAssertKeyed(expr->queryChild(i)))
  12969. return true;
  12970. return false;
  12971. }
  12972. bool canEvaluateGlobally(IHqlExpression * expr)
  12973. {
  12974. if (isContextDependent(expr))
  12975. return false;
  12976. if (!isIndependentOfScope(expr))
  12977. return false;
  12978. return true;
  12979. }
  12980. bool preservesValue(ITypeInfo * after, IHqlExpression * expr)
  12981. {
  12982. ITypeInfo * before = expr->queryType();
  12983. if (preservesValue(after, before))
  12984. return true;
  12985. //Special case casting a constant to a different length of the same type
  12986. //e.g., string/integer. It may preserve value in this special case.
  12987. //don't allow int->string because it isn't symetric
  12988. IValue * value = expr->queryValue();
  12989. if (!value || (before->getTypeCode() != after->getTypeCode()))
  12990. return false;
  12991. OwnedIValue castValue = value->castTo(after);
  12992. if (!castValue)
  12993. return false;
  12994. OwnedIValue recastValue = castValue->castTo(before);
  12995. if (!recastValue)
  12996. return false;
  12997. return (recastValue->compare(value) == 0);
  12998. }
  12999. static const unsigned UNLIMITED_REPEAT = (unsigned)-1;
  13000. unsigned getRepeatMin(IHqlExpression * expr)
  13001. {
  13002. IHqlExpression * minExpr = queryRealChild(expr, 1);
  13003. if (minExpr)
  13004. return (unsigned)minExpr->queryValue()->getIntValue();
  13005. return 0;
  13006. }
  13007. unsigned getRepeatMax(IHqlExpression * expr)
  13008. {
  13009. IHqlExpression * minExpr = queryRealChild(expr, 1);
  13010. IHqlExpression * maxExpr = queryRealChild(expr, 2);
  13011. if (minExpr && maxExpr)
  13012. {
  13013. if (maxExpr->getOperator() == no_any)
  13014. return UNLIMITED_REPEAT;
  13015. return (unsigned)maxExpr->queryValue()->getIntValue();
  13016. }
  13017. if (minExpr)
  13018. return (unsigned)minExpr->queryValue()->getIntValue();
  13019. return (unsigned)UNLIMITED_REPEAT; // no limit...
  13020. }
  13021. bool isStandardRepeat(IHqlExpression * expr)
  13022. {
  13023. if (expr->hasAttribute(minimalAtom)) return false;
  13024. unsigned min = getRepeatMin(expr);
  13025. unsigned max = getRepeatMax(expr);
  13026. if ((min == 0) && (max == 1)) return true;
  13027. if ((min == 0) && (max == UNLIMITED_REPEAT)) return true;
  13028. if ((min == 1) && (max == UNLIMITED_REPEAT)) return true;
  13029. return false;
  13030. }
  13031. IHqlExpression * queryOnlyField(IHqlExpression * record)
  13032. {
  13033. IHqlExpression * ret = NULL;
  13034. ForEachChild(i, record)
  13035. {
  13036. IHqlExpression * cur = record->queryChild(i);
  13037. switch (cur->getOperator())
  13038. {
  13039. case no_field:
  13040. if (ret)
  13041. return NULL;
  13042. ret = cur;
  13043. break;
  13044. }
  13045. }
  13046. return ret;
  13047. }
  13048. bool isPureActivity(IHqlExpression * expr)
  13049. {
  13050. unsigned max = expr->numChildren();
  13051. for (unsigned i = getNumChildTables(expr); i < max; i++)
  13052. {
  13053. IHqlExpression * cur = expr->queryChild(i);
  13054. if (!cur->isPure() || containsSkip(cur))
  13055. return false;
  13056. }
  13057. return true;
  13058. }
  13059. bool isPureActivityIgnoringSkip(IHqlExpression * expr)
  13060. {
  13061. unsigned max = expr->numChildren();
  13062. const unsigned mask = HEFimpure & ~(HEFcontainsSkip);
  13063. for (unsigned i = getNumChildTables(expr); i < max; i++)
  13064. {
  13065. if (expr->queryChild(i)->getInfoFlags() & mask)
  13066. return false;
  13067. }
  13068. return true;
  13069. }
  13070. bool assignsContainSkip(IHqlExpression * expr)
  13071. {
  13072. switch (expr->getOperator())
  13073. {
  13074. case no_newtransform:
  13075. case no_transform:
  13076. case no_assignall:
  13077. {
  13078. ForEachChild(i, expr)
  13079. {
  13080. if (assignsContainSkip(expr->queryChild(i)))
  13081. return true;
  13082. }
  13083. return false;
  13084. }
  13085. case no_assign:
  13086. return containsSkip(expr->queryChild(1));
  13087. case no_alias_scope:
  13088. return assignsContainSkip(expr->queryChild(0));
  13089. default:
  13090. return false;
  13091. }
  13092. }
  13093. extern HQL_API bool isKnownTransform(IHqlExpression * transform)
  13094. {
  13095. switch (transform->getOperator())
  13096. {
  13097. case no_transform:
  13098. case no_newtransform:
  13099. return true;
  13100. case no_alias_scope:
  13101. return isKnownTransform(transform->queryChild(0));
  13102. }
  13103. return false;
  13104. }
  13105. extern HQL_API bool hasUnknownTransform(IHqlExpression * expr)
  13106. {
  13107. switch (expr->getOperator())
  13108. {
  13109. case no_aggregate:
  13110. if (expr->hasAttribute(mergeTransformAtom))
  13111. return true;
  13112. break;
  13113. case no_inlinetable:
  13114. {
  13115. IHqlExpression * transforms = expr->queryChild(0);
  13116. ForEachChild(i, transforms)
  13117. if (!isKnownTransform(transforms->queryChild(i)))
  13118. return true;
  13119. return false;
  13120. }
  13121. }
  13122. return !isKnownTransform(queryNewColumnProvider(expr));
  13123. }
  13124. bool isContextDependent(IHqlExpression * expr, bool ignoreFailures, bool ignoreGraph)
  13125. {
  13126. unsigned flags = expr->getInfoFlags();
  13127. unsigned mask = HEFcontextDependent;
  13128. if (ignoreFailures)
  13129. mask = HEFcontextDependentNoThrow;
  13130. if (ignoreGraph)
  13131. mask &= ~HEFgraphDependent;
  13132. if ((flags & mask) == 0)
  13133. return false;
  13134. return true;
  13135. }
  13136. bool isPureCanSkip(IHqlExpression * expr)
  13137. {
  13138. return (expr->getInfoFlags() & (HEFvolatile|HEFaction|HEFthrowscalar|HEFthrowds)) == 0;
  13139. }
  13140. bool hasSideEffects(IHqlExpression * expr)
  13141. {
  13142. return (expr->getInfoFlags() & (HEFthrowscalar|HEFthrowds)) != 0;
  13143. }
  13144. bool isPureVirtual(IHqlExpression * expr)
  13145. {
  13146. switch (expr->getOperator())
  13147. {
  13148. case no_purevirtual:
  13149. return true;
  13150. case no_funcdef:
  13151. return isPureVirtual(expr->queryChild(0));
  13152. default:
  13153. return false;
  13154. }
  13155. }
  13156. bool transformHasSkipAttr(IHqlExpression * transform)
  13157. {
  13158. ForEachChild(i, transform)
  13159. {
  13160. IHqlExpression * cur = transform->queryChild(i);
  13161. if (cur->getOperator() == no_skip)
  13162. return true;
  13163. }
  13164. return false;
  13165. }
  13166. bool isPureInlineDataset(IHqlExpression * expr)
  13167. {
  13168. assertex(expr->getOperator() == no_inlinetable);
  13169. IHqlExpression * values = expr->queryChild(0);
  13170. ForEachChild(i, values)
  13171. {
  13172. IHqlExpression * transform = values->queryChild(i);
  13173. if (!transform->isPure() || containsSkip(transform))
  13174. return false;
  13175. }
  13176. return true;
  13177. }
  13178. IHqlExpression * getActiveTableSelector()
  13179. {
  13180. return LINK(cachedActiveTableExpr);
  13181. }
  13182. IHqlExpression * queryActiveTableSelector()
  13183. {
  13184. return cachedActiveTableExpr;
  13185. }
  13186. IHqlExpression * getSelf(IHqlExpression * ds)
  13187. {
  13188. return createSelector(no_self, ds, NULL);
  13189. }
  13190. IHqlExpression * querySelfReference()
  13191. {
  13192. return cachedSelfReferenceExpr;
  13193. }
  13194. IHqlExpression * queryNullRecord()
  13195. {
  13196. return cachedNullRecord;
  13197. }
  13198. IHqlExpression * queryNullRowRecord()
  13199. {
  13200. return cachedNullRowRecord;
  13201. }
  13202. IHqlExpression * createNullDataset()
  13203. {
  13204. return createDataset(no_null, LINK(queryNullRecord()));
  13205. }
  13206. IHqlExpression * createNullDictionary()
  13207. {
  13208. return createDictionary(no_null, LINK(queryNullRecord()));
  13209. }
  13210. bool removeAttribute(HqlExprArray & args, IAtom * name)
  13211. {
  13212. bool removed = false;
  13213. ForEachItemInRev(idx, args)
  13214. {
  13215. IHqlExpression & cur = args.item(idx);
  13216. if (cur.isAttribute() && (cur.queryName() == name))
  13217. {
  13218. args.remove(idx);
  13219. removed = true;
  13220. }
  13221. }
  13222. return removed;
  13223. }
  13224. void removeAttributes(HqlExprArray & args)
  13225. {
  13226. ForEachItemInRev(idx, args)
  13227. {
  13228. IHqlExpression & cur = args.item(idx);
  13229. if (cur.isAttribute())
  13230. args.remove(idx);
  13231. }
  13232. }
  13233. IHqlExpression * queryRecord(ITypeInfo * type)
  13234. {
  13235. ITypeInfo * recordType = queryRecordType(type);
  13236. if (recordType)
  13237. return queryExpression(recordType);
  13238. return NULL;
  13239. }
  13240. //NB: An ifblock is counted as a single payload field.
  13241. unsigned numPayloadFields(IHqlExpression * index)
  13242. {
  13243. IHqlExpression * payloadAttr = index->queryAttribute(_payload_Atom);
  13244. if (payloadAttr)
  13245. return (unsigned)getIntValue(payloadAttr->queryChild(0));
  13246. if (getBoolAttribute(index, filepositionAtom, true))
  13247. return 1;
  13248. return 0;
  13249. }
  13250. unsigned numKeyedFields(IHqlExpression * index)
  13251. {
  13252. return getFlatFieldCount(index->queryRecord())-numPayloadFields(index);
  13253. }
  13254. unsigned firstPayloadField(IHqlExpression * index)
  13255. {
  13256. return firstPayloadField(index->queryRecord(), numPayloadFields(index));
  13257. }
  13258. unsigned firstPayloadField(IHqlExpression * record, unsigned cnt)
  13259. {
  13260. unsigned max = record->numChildren();
  13261. if (cnt == 0)
  13262. return max;
  13263. while (max--)
  13264. {
  13265. IHqlExpression * cur = record->queryChild(max);
  13266. switch (cur->getOperator())
  13267. {
  13268. case no_field:
  13269. case no_record:
  13270. case no_ifblock:
  13271. if (--cnt == 0)
  13272. return max;
  13273. break;
  13274. }
  13275. }
  13276. return 0;
  13277. }
  13278. IHqlExpression * createSelector(node_operator op, IHqlExpression * ds, IHqlExpression * seq)
  13279. {
  13280. // OwnedHqlExpr record = getUnadornedExpr(ds->queryRecord());
  13281. IHqlExpression * dsRecord = ds->queryRecord();
  13282. assertex(dsRecord);
  13283. IHqlExpression * record = dsRecord->queryBody();
  13284. switch (op)
  13285. {
  13286. case no_left:
  13287. case no_right:
  13288. case no_top:
  13289. assertex(seq && seq->isAttribute());
  13290. return createRow(op, LINK(record), LINK(seq));
  13291. case no_self:
  13292. {
  13293. //seq is set when generating code unique target selectors
  13294. return createRow(op, LINK(record), LINK(seq));
  13295. }
  13296. case no_none:
  13297. return LINK(ds);
  13298. case no_activetable:
  13299. return LINK(cachedActiveTableExpr);
  13300. default:
  13301. return createValue(op);
  13302. }
  13303. }
  13304. static UniqueSequenceCounter uidSequence;
  13305. IHqlExpression * createUniqueId()
  13306. {
  13307. unsigned __int64 uid = uidSequence.next();
  13308. return createSequence(no_attr, NULL, _uid_Atom, uid);
  13309. }
  13310. static UniqueSequenceCounter counterSequence;
  13311. IHqlExpression * createCounter()
  13312. {
  13313. return createSequence(no_counter, makeIntType(8, false), NULL, counterSequence.next());
  13314. }
  13315. static UniqueSequenceCounter selectorSequence;
  13316. IHqlExpression * createUniqueSelectorSequence()
  13317. {
  13318. unsigned __int64 seq = selectorSequence.next();
  13319. return createSequence(no_attr, NULL, _selectorSequence_Atom, seq);
  13320. }
  13321. IHqlExpression * createSelectorSequence(unsigned __int64 seq)
  13322. {
  13323. return createSequence(no_attr, NULL, _selectorSequence_Atom, seq);
  13324. }
  13325. static UniqueSequenceCounter rowsidSequence;
  13326. IHqlExpression * createUniqueRowsId()
  13327. {
  13328. unsigned __int64 seq = rowsidSequence.next();
  13329. return createSequence(no_attr, NULL, _rowsid_Atom, seq);
  13330. }
  13331. static UniqueSequenceCounter sequenceExprSequence;
  13332. IHqlExpression * createSequenceExpr()
  13333. {
  13334. unsigned __int64 seq = sequenceExprSequence.next();
  13335. return createSequence(no_sequence, makeIntType(sizeof(size32_t), false), NULL, seq);
  13336. }
  13337. IHqlExpression * createSelectorSequence()
  13338. {
  13339. #ifdef USE_SELSEQ_UID
  13340. return createUniqueSelectorSequence();
  13341. #else
  13342. return LINK(defaultSelectorSequenceExpr);
  13343. #endif
  13344. }
  13345. IHqlExpression * createDummySelectorSequence()
  13346. {
  13347. return LINK(defaultSelectorSequenceExpr);
  13348. }
  13349. IHqlExpression * queryNewSelectAttrExpr()
  13350. {
  13351. return newSelectAttrExpr;
  13352. }
  13353. //Follow inheritance structure when getting property value.
  13354. IHqlExpression * queryRecordAttribute(IHqlExpression * record, IAtom * name)
  13355. {
  13356. IHqlExpression * match = record->queryAttribute(name);
  13357. if (match)
  13358. return match;
  13359. ForEachChild(i, record)
  13360. {
  13361. IHqlExpression * cur = record->queryChild(i);
  13362. switch (cur->getOperator())
  13363. {
  13364. case no_record:
  13365. return queryRecordAttribute(cur, name);
  13366. case no_field:
  13367. case no_ifblock:
  13368. return NULL;
  13369. }
  13370. }
  13371. return NULL;
  13372. }
  13373. bool isSortDistribution(IHqlExpression * distribution)
  13374. {
  13375. return (distribution && distribution->isAttribute() && (distribution->queryName() == sortedAtom));
  13376. }
  13377. bool isChooseNAllLimit(IHqlExpression * limit)
  13378. {
  13379. IValue * value = limit->queryValue();
  13380. return (value && (value->getIntValue() == CHOOSEN_ALL_LIMIT));
  13381. }
  13382. bool activityMustBeCompound(IHqlExpression * expr)
  13383. {
  13384. switch (expr->getOperator())
  13385. {
  13386. case no_keyedlimit:
  13387. return true;
  13388. case no_filter:
  13389. return filterIsKeyed(expr);
  13390. case no_newaggregate:
  13391. case no_newusertable:
  13392. case no_aggregate:
  13393. case no_usertable:
  13394. case no_hqlproject:
  13395. return expr->hasAttribute(keyedAtom);
  13396. }
  13397. return false;
  13398. }
  13399. bool isSequentialActionList(IHqlExpression * expr)
  13400. {
  13401. switch (expr->getOperator())
  13402. {
  13403. case no_orderedactionlist:
  13404. case no_sequential:
  13405. return true;
  13406. }
  13407. return false;
  13408. }
  13409. bool isSelectFirstRow(IHqlExpression * expr)
  13410. {
  13411. if (expr->getOperator() != no_selectnth)
  13412. return false;
  13413. IValue * value = expr->queryChild(1)->queryValue();
  13414. return value && (value->getIntValue() == 1);
  13415. }
  13416. bool includeChildInDependents(IHqlExpression * expr, unsigned which)
  13417. {
  13418. switch (expr->getOperator())
  13419. {
  13420. case no_keyindex:
  13421. case no_newkeyindex:
  13422. return (which != 0);
  13423. case no_table:
  13424. return which <= 2;
  13425. }
  13426. return true;
  13427. }
  13428. IHqlExpression * queryExpression(ITypeInfo * type)
  13429. {
  13430. if (!type) return NULL;
  13431. ITypeInfo * indirect = queryModifier(type, typemod_indirect);
  13432. if (indirect)
  13433. return static_cast<IHqlExpression *>(indirect->queryModifierExtra());
  13434. return QUERYINTERFACE(queryUnqualifiedType(type), IHqlExpression);
  13435. }
  13436. IHqlExpression * queryExpression(IHqlDataset * ds)
  13437. {
  13438. if (!ds) return NULL;
  13439. return ds->queryExpression();
  13440. }
  13441. IHqlScope * queryScope(ITypeInfo * type)
  13442. {
  13443. if (!type) return NULL;
  13444. return QUERYINTERFACE(queryUnqualifiedType(type), IHqlScope);
  13445. }
  13446. IHqlRemoteScope * queryRemoteScope(IHqlScope * scope)
  13447. {
  13448. return dynamic_cast<IHqlRemoteScope *>(scope);
  13449. }
  13450. IHqlAlienTypeInfo * queryAlienType(ITypeInfo * type)
  13451. {
  13452. return QUERYINTERFACE(queryUnqualifiedType(type), IHqlAlienTypeInfo);
  13453. }
  13454. bool isSameUnqualifiedType(ITypeInfo * l, ITypeInfo * r)
  13455. {
  13456. return queryUnqualifiedType(l) == queryUnqualifiedType(r);
  13457. }
  13458. bool isSameFullyUnqualifiedType(ITypeInfo * l, ITypeInfo * r)
  13459. {
  13460. Owned<ITypeInfo> ul = getFullyUnqualifiedType(l);
  13461. Owned<ITypeInfo> ur = getFullyUnqualifiedType(r);
  13462. return ul == ur;
  13463. }
  13464. bool recordTypesMatch(ITypeInfo * left, ITypeInfo * right)
  13465. {
  13466. if (!left || !right)
  13467. return (left == right);
  13468. if (queryUnqualifiedType(queryRecordType(left)) == queryUnqualifiedType(queryRecordType(right)))
  13469. return true;
  13470. IHqlExpression * leftRecord = queryRecord(left);
  13471. IHqlExpression * rightRecord = queryRecord(right);
  13472. if (!leftRecord || !rightRecord)
  13473. return leftRecord == rightRecord;
  13474. if (leftRecord->hasAttribute(abstractAtom) || rightRecord->hasAttribute(abstractAtom))
  13475. return true;
  13476. //This test compares the real record structure, ignoring names etc. The code above just short-cicuits this test.
  13477. OwnedHqlExpr unadornedLeft = getUnadornedRecordOrField(leftRecord);
  13478. OwnedHqlExpr unadornedRight = getUnadornedRecordOrField(rightRecord);
  13479. if (unadornedLeft == unadornedRight)
  13480. return true;
  13481. #ifdef _DEBUG
  13482. debugFindFirstDifference(unadornedLeft, unadornedRight);
  13483. #endif
  13484. return false;
  13485. }
  13486. void assertRecordTypesMatch(ITypeInfo * left, ITypeInfo * right)
  13487. {
  13488. if (recordTypesMatch(left, right))
  13489. return;
  13490. EclIR::dbglogIR(2, left, right);
  13491. throwUnexpected();
  13492. }
  13493. void assertRecordTypesMatch(IHqlExpression * left, IHqlExpression * right)
  13494. {
  13495. assertRecordTypesMatch(left->queryRecordType(), right->queryRecordType());
  13496. }
  13497. bool recordTypesMatch(IHqlExpression * left, IHqlExpression * right)
  13498. {
  13499. return recordTypesMatch(left->queryRecordType(), right->queryRecordType());
  13500. }
  13501. bool recordTypesMatchIgnorePayload(IHqlExpression *left, IHqlExpression *right)
  13502. {
  13503. OwnedHqlExpr simpleLeft = removeAttribute(left->queryRecord(), _payload_Atom);
  13504. OwnedHqlExpr simpleRight = removeAttribute(right->queryRecord(), _payload_Atom);
  13505. return recordTypesMatch(simpleLeft->queryType(), simpleRight->queryType());
  13506. }
  13507. IHqlExpression * queryTransformSingleAssign(IHqlExpression * transform)
  13508. {
  13509. if ((transform->numChildren() == 0) || queryRealChild(transform, 1))
  13510. return NULL;
  13511. IHqlExpression * assign = transform->queryChild(0);
  13512. if (assign->getOperator() == no_assignall)
  13513. {
  13514. if (assign->numChildren() != 1)
  13515. return NULL;
  13516. assign = assign->queryChild(0);
  13517. }
  13518. if (assign->getOperator() != no_assign)
  13519. return NULL;
  13520. return assign;
  13521. }
  13522. IHqlExpression * convertToSimpleAggregate(IHqlExpression * expr)
  13523. {
  13524. if ((expr->getOperator() == no_select) && expr->queryAttribute(newAtom))
  13525. {
  13526. expr = expr->queryChild(0);
  13527. if (!isSelectFirstRow(expr))
  13528. return NULL;
  13529. expr = expr->queryChild(0);
  13530. }
  13531. if (expr->getOperator() == no_compound_childaggregate)
  13532. expr = expr->queryChild(0);
  13533. if (expr->getOperator() != no_newaggregate)
  13534. return NULL;
  13535. if (datasetHasGroupBy(expr))
  13536. return NULL;
  13537. IHqlExpression * transform = expr->queryChild(2);
  13538. IHqlExpression * assign = queryTransformSingleAssign(transform);
  13539. if (!assign)
  13540. return NULL;
  13541. IHqlExpression * lhs = assign->queryChild(0);
  13542. IHqlExpression * rhs = assign->queryChild(1);
  13543. node_operator newop;
  13544. unsigned numArgs = 0;
  13545. switch (rhs->getOperator())
  13546. {
  13547. case no_avegroup: newop = no_ave; numArgs = 1; break;
  13548. case no_countgroup: newop = no_count; break;
  13549. case no_mingroup: newop = no_min; numArgs = 1; break;
  13550. case no_maxgroup: newop = no_max; numArgs = 1; break;
  13551. case no_sumgroup: newop = no_sum; numArgs = 1; break;
  13552. case no_existsgroup: newop = no_exists; break;
  13553. default:
  13554. return NULL;
  13555. }
  13556. if ((numArgs != 0) && (lhs->queryType() != rhs->queryType()))
  13557. return NULL;
  13558. IHqlExpression * ds = expr->queryChild(0);
  13559. loop
  13560. {
  13561. node_operator op = ds->getOperator();
  13562. if ((op != no_sorted) && (op != no_distributed) && (op != no_preservemeta) && (op != no_alias_scope))
  13563. break;
  13564. ds = ds->queryChild(0);
  13565. }
  13566. ::Link(ds);
  13567. IHqlExpression * filter = queryRealChild(rhs, numArgs);
  13568. if (filter)
  13569. ds = createDataset(no_filter, ds, LINK(filter));
  13570. HqlExprArray args;
  13571. args.append(*ds);
  13572. for (unsigned i=0; i < numArgs; i++)
  13573. args.append(*LINK(rhs->queryChild(i)));
  13574. IHqlExpression * keyed = rhs->queryAttribute(keyedAtom);
  13575. if (keyed)
  13576. args.append(*LINK(keyed));
  13577. OwnedHqlExpr aggregate = createValue(newop, rhs->getType(), args);
  13578. return ensureExprType(aggregate, lhs->queryType());
  13579. }
  13580. IHqlExpression * queryAggregateFilter(IHqlExpression * expr)
  13581. {
  13582. switch (expr->getOperator())
  13583. {
  13584. case no_countgroup:
  13585. case no_existsgroup:
  13586. return queryRealChild(expr, 0);
  13587. case no_sumgroup:
  13588. case no_vargroup:
  13589. case no_covargroup:
  13590. case no_corrgroup:
  13591. case no_maxgroup:
  13592. case no_mingroup:
  13593. case no_avegroup:
  13594. return queryRealChild(expr, 1);
  13595. }
  13596. throwUnexpected();
  13597. }
  13598. node_operator querySingleAggregate(IHqlExpression * expr, bool canFilterArg, bool canBeGrouped, bool canCast)
  13599. {
  13600. //This needs to only matche examples suported by the function above (with canBeGrouped set to false).
  13601. switch (expr->getOperator())
  13602. {
  13603. case no_compound_childaggregate:
  13604. case no_compound_diskaggregate:
  13605. case no_compound_indexaggregate:
  13606. expr = expr->queryChild(0);
  13607. break;
  13608. }
  13609. if (expr->getOperator() != no_newaggregate)
  13610. return no_none;
  13611. if (!canBeGrouped && (datasetHasGroupBy(expr) || isGrouped(expr->queryChild(0))))
  13612. return no_none;
  13613. IHqlExpression * transform = expr->queryChild(2);
  13614. if (!canBeGrouped && (transform->numChildren() != 1))
  13615. return no_none;
  13616. node_operator matchedOp = no_none;
  13617. ForEachChild(i, transform)
  13618. {
  13619. IHqlExpression * assign = transform->queryChild(i);
  13620. if (assign->getOperator() != no_assign)
  13621. return no_none;
  13622. IHqlExpression * rhs = assign->queryChild(1);
  13623. node_operator curOp = rhs->getOperator();
  13624. switch (curOp)
  13625. {
  13626. case NO_AGGREGATEGROUP:
  13627. if (matchedOp != no_none)
  13628. return no_none;
  13629. break;
  13630. default:
  13631. if (!canBeGrouped)
  13632. return no_none;
  13633. //A non aggregate, so iterate again.
  13634. continue;
  13635. }
  13636. if (assign->queryChild(0)->queryType() != rhs->queryType())
  13637. {
  13638. if (!canCast)
  13639. return no_none;
  13640. switch (curOp)
  13641. {
  13642. case no_existsgroup:
  13643. case no_countgroup:
  13644. break;
  13645. default:
  13646. return no_none;
  13647. }
  13648. }
  13649. if (!canFilterArg && queryAggregateFilter(rhs))
  13650. return no_none;
  13651. matchedOp = curOp;
  13652. }
  13653. return matchedOp;
  13654. }
  13655. node_operator querySimpleAggregate(IHqlExpression * expr, bool canFilterArg, bool canCast)
  13656. {
  13657. //This needs to match convertToSimpleAggregate() above.
  13658. return querySingleAggregate(expr, canFilterArg, false, canCast);
  13659. }
  13660. bool isSimpleCountAggregate(IHqlExpression * expr, bool canFilterArg)
  13661. {
  13662. return querySimpleAggregate(expr, canFilterArg, true) == no_countgroup;
  13663. }
  13664. bool isSimpleCountExistsAggregate(IHqlExpression * expr, bool canFilterArg, bool canCast)
  13665. {
  13666. node_operator op = querySimpleAggregate(expr, canFilterArg, canCast);
  13667. return (op == no_countgroup) || (op == no_existsgroup);
  13668. }
  13669. bool isKeyedCountAggregate(IHqlExpression * aggregate)
  13670. {
  13671. IHqlExpression * transform = aggregate->queryChild(2);
  13672. IHqlExpression * assign = transform->queryChild(0);
  13673. if (!assign || assign->getOperator() != no_assign)
  13674. return false;
  13675. IHqlExpression * count = assign->queryChild(1);
  13676. if (count->getOperator() != no_countgroup)
  13677. return false;
  13678. return count->hasAttribute(keyedAtom);
  13679. }
  13680. static bool getBoolAttributeValue(IHqlExpression * attr)
  13681. {
  13682. IHqlExpression * value = attr->queryChild(0);
  13683. //No argument implies true
  13684. if (!value)
  13685. return true;
  13686. //If it is a constant return it.
  13687. if (value->queryValue())
  13688. return getBoolValue(value, true);
  13689. //Not a constant => fold the expression
  13690. OwnedHqlExpr folded = foldHqlExpression(value);
  13691. if (folded->queryValue())
  13692. return getBoolValue(folded, true);
  13693. throwError1(HQLERR_PropertyArgumentNotConstant, attr->queryName()->str());
  13694. }
  13695. bool getBoolAttribute(IHqlExpression * expr, IAtom * name, bool dft)
  13696. {
  13697. if (!expr)
  13698. return dft;
  13699. IHqlExpression * attr = expr->queryAttribute(name);
  13700. if (!attr)
  13701. return dft;
  13702. return getBoolAttributeValue(attr);
  13703. }
  13704. bool getBoolAttributeInList(IHqlExpression * expr, IAtom * search, bool dft)
  13705. {
  13706. IHqlExpression * match = queryAttributeInList(search, expr);
  13707. if (!match)
  13708. return dft;
  13709. return getBoolAttributeValue(match);
  13710. }
  13711. IHqlExpression * queryOriginalRecord(IHqlExpression * expr)
  13712. {
  13713. return queryOriginalRecord(expr->queryType());
  13714. }
  13715. IHqlExpression * queryOriginalTypeExpression(ITypeInfo * t)
  13716. {
  13717. loop
  13718. {
  13719. typemod_t modifier = t->queryModifier();
  13720. if (modifier == typemod_none)
  13721. break;
  13722. if (modifier == typemod_original)
  13723. {
  13724. IHqlExpression * originalExpr = static_cast<IHqlExpression *>(t->queryModifierExtra());
  13725. if (originalExpr->queryType()->getTypeCode() == t->getTypeCode())
  13726. return originalExpr;
  13727. }
  13728. t = t->queryTypeBase();
  13729. }
  13730. return queryExpression(t);
  13731. }
  13732. IHqlExpression * queryOriginalRecord(ITypeInfo * t)
  13733. {
  13734. t = queryRecordType(t);
  13735. if (!t)
  13736. return NULL;
  13737. loop
  13738. {
  13739. typemod_t modifier = t->queryModifier();
  13740. if (modifier == typemod_none)
  13741. return queryExpression(t);
  13742. if (modifier == typemod_original)
  13743. {
  13744. IHqlExpression * originalExpr = static_cast<IHqlExpression *>(t->queryModifierExtra());
  13745. if (originalExpr->getOperator() == no_record)
  13746. return originalExpr;
  13747. }
  13748. t = t->queryTypeBase();
  13749. }
  13750. return queryExpression(t);
  13751. }
  13752. ITypeInfo * createRecordType(IHqlExpression * record)
  13753. {
  13754. if (record->getOperator() != no_record)
  13755. return LINK(record->queryRecordType());
  13756. if (record->queryBody(true) == record)
  13757. return record->getType();
  13758. return makeOriginalModifier(record->getType(), LINK(record));
  13759. }
  13760. ITypeInfo * getSumAggType(ITypeInfo * argType)
  13761. {
  13762. type_t tc = argType->getTypeCode();
  13763. switch (tc)
  13764. {
  13765. case type_packedint:
  13766. case type_swapint:
  13767. case type_bitfield:
  13768. return makeIntType(8, true);
  13769. case type_int:
  13770. if (argType->getSize() < 8)
  13771. return makeIntType(8, true);
  13772. return LINK(argType);
  13773. case type_real:
  13774. return makeRealType(8);
  13775. case type_decimal:
  13776. {
  13777. //A guess is to add 12 more digits
  13778. unsigned oldDigits = argType->getDigits();
  13779. if (oldDigits == UNKNOWN_LENGTH)
  13780. return LINK(argType);
  13781. unsigned oldPrecision = argType->getPrecision();
  13782. unsigned newDigits = argType->getDigits()+12;
  13783. if (newDigits - oldPrecision > MAX_DECIMAL_LEADING)
  13784. newDigits = MAX_DECIMAL_LEADING + oldPrecision;
  13785. return makeDecimalType(newDigits, oldPrecision, argType->isSigned());
  13786. }
  13787. default:
  13788. return LINK(argType);
  13789. }
  13790. }
  13791. ITypeInfo * getSumAggType(IHqlExpression * arg)
  13792. {
  13793. return getSumAggType(arg->queryType());
  13794. }
  13795. //Return a base attribute ignoring any delayed evaluation, so we can find out the type of the base object
  13796. //and get an approximation to the definition when it is required.
  13797. IHqlExpression * queryNonDelayedBaseAttribute(IHqlExpression * expr)
  13798. {
  13799. if (!expr)
  13800. return NULL;
  13801. loop
  13802. {
  13803. node_operator op = expr->getOperator();
  13804. switch (op)
  13805. {
  13806. case no_call:
  13807. case no_libraryscopeinstance:
  13808. expr = expr->queryDefinition();
  13809. break;
  13810. case no_funcdef:
  13811. expr = expr->queryChild(0);
  13812. break;
  13813. case no_delayedselect:
  13814. case no_internalselect:
  13815. case no_libraryselect:
  13816. case no_unboundselect:
  13817. expr = expr->queryChild(2);
  13818. break;
  13819. default:
  13820. return expr;
  13821. }
  13822. }
  13823. }
  13824. extern bool areAllBasesFullyBound(IHqlExpression * module)
  13825. {
  13826. if (module->getOperator() == no_param)
  13827. return false;
  13828. ForEachChild(i, module)
  13829. {
  13830. IHqlExpression * cur = module->queryChild(i);
  13831. if (!cur->isAttribute() && !areAllBasesFullyBound(cur))
  13832. return false;
  13833. }
  13834. return true;
  13835. }
  13836. bool isUpdatedConditionally(IHqlExpression * expr)
  13837. {
  13838. IHqlExpression * updateAttr = expr->queryAttribute(updateAtom);
  13839. return (updateAttr && !updateAttr->queryAttribute(alwaysAtom));
  13840. }
  13841. ITypeInfo * getTypedefType(IHqlExpression * expr)
  13842. {
  13843. //Don't create annotate with a typedef modifier if it doesn't add any information - e.g., maxlength
  13844. if ((expr->getOperator() == no_typedef) && (expr->numChildren() == 0))
  13845. return expr->getType();
  13846. return makeOriginalModifier(expr->getType(), LINK(expr));
  13847. }
  13848. void extendAdd(SharedHqlExpr & value, IHqlExpression * expr)
  13849. {
  13850. if (value)
  13851. value.setown(createValue(no_add, value->getType(), LINK(value), LINK(expr)));
  13852. else
  13853. value.set(expr);
  13854. }
  13855. //Not certain of the best representation. At the moment just take the record, and add an abstract flag
  13856. extern HQL_API IHqlExpression * createAbstractRecord(IHqlExpression * record)
  13857. {
  13858. HqlExprArray args;
  13859. if (record)
  13860. unwindChildren(args, record);
  13861. //Alteranative code which should also work, but may require changes to the existing (deprecated) virtual dataset code....
  13862. //if (record)
  13863. // args.append(*LINK(record));
  13864. args.append(*createAttribute(abstractAtom));
  13865. return createRecord(args);
  13866. }
  13867. extern HQL_API IHqlExpression * createSortList(HqlExprArray & elements)
  13868. {
  13869. return createValue(no_sortlist, makeSortListType(NULL), elements);
  13870. }
  13871. IHqlExpression * cloneFieldMangleName(IHqlExpression * field)
  13872. {
  13873. StringBuffer newName;
  13874. newName.append(field->queryId()->str()).append("_").append(getUniqueId());
  13875. HqlExprArray children;
  13876. unwindChildren(children, field);
  13877. return createField(createIdAtom(newName), field->getType(), children);
  13878. }
  13879. //==============================================================================================================
  13880. static void safeLookupSymbol(HqlLookupContext & ctx, IHqlScope * modScope, IIdAtom * name)
  13881. {
  13882. try
  13883. {
  13884. OwnedHqlExpr resolved = modScope->lookupSymbol(name, LSFpublic, ctx);
  13885. if (!resolved || !resolved->isMacro())
  13886. return;
  13887. //Macros need special processing to expand their definitions.
  13888. HqlLookupContext childContext(ctx);
  13889. childContext.createDependencyEntry(modScope, name);
  13890. OwnedHqlExpr expanded = expandMacroDefinition(resolved, childContext, false);
  13891. }
  13892. catch (IException * e)
  13893. {
  13894. e->Release();
  13895. }
  13896. }
  13897. static void gatherAttributeDependencies(HqlLookupContext & ctx, IHqlScope * modScope)
  13898. {
  13899. modScope->ensureSymbolsDefined(ctx);
  13900. HqlExprArray symbols;
  13901. modScope->getSymbols(symbols);
  13902. symbols.sort(compareSymbolsByName);
  13903. ForEachItemIn(i, symbols)
  13904. safeLookupSymbol(ctx, modScope, symbols.item(i).queryId());
  13905. }
  13906. static void gatherAttributeDependencies(HqlLookupContext & ctx, const char * item)
  13907. {
  13908. try
  13909. {
  13910. IIdAtom * moduleName = NULL;
  13911. IIdAtom * attrName = NULL;
  13912. const char * dot = strrchr(item, '.');
  13913. if (dot)
  13914. {
  13915. moduleName = createIdAtom(item, dot-item);
  13916. attrName = createIdAtom(dot+1);
  13917. }
  13918. else
  13919. moduleName = createIdAtom(item);
  13920. OwnedHqlExpr resolved = ctx.queryRepository()->queryRootScope()->lookupSymbol(moduleName, LSFpublic, ctx);
  13921. if (resolved)
  13922. {
  13923. IHqlScope * scope = resolved->queryScope();
  13924. if (scope)
  13925. {
  13926. if (attrName)
  13927. safeLookupSymbol(ctx, scope, attrName);
  13928. else
  13929. gatherAttributeDependencies(ctx, scope);
  13930. }
  13931. }
  13932. }
  13933. catch (IException * e)
  13934. {
  13935. e->Release();
  13936. }
  13937. }
  13938. extern HQL_API IPropertyTree * gatherAttributeDependencies(IEclRepository * dataServer, const char * items)
  13939. {
  13940. HqlParseContext parseCtx(dataServer, NULL);
  13941. parseCtx.nestedDependTree.setown(createPTree("Dependencies"));
  13942. Owned<IErrorReceiver> errorHandler = createNullErrorReceiver();
  13943. HqlLookupContext ctx(parseCtx, errorHandler);
  13944. if (items && *items)
  13945. {
  13946. loop
  13947. {
  13948. const char * comma = strchr(items, ',');
  13949. if (!comma)
  13950. break;
  13951. StringBuffer next;
  13952. next.append(comma-items, items);
  13953. gatherAttributeDependencies(ctx, next.str());
  13954. items = comma+1;
  13955. }
  13956. gatherAttributeDependencies(ctx, items);
  13957. }
  13958. else
  13959. {
  13960. HqlScopeArray scopes;
  13961. getRootScopes(scopes, dataServer, ctx);
  13962. scopes.sort(compareScopesByName);
  13963. ForEachItemIn(i, scopes)
  13964. {
  13965. IHqlScope & cur = scopes.item(i);
  13966. gatherAttributeDependencies(ctx, &cur);
  13967. }
  13968. }
  13969. return parseCtx.nestedDependTree.getClear();
  13970. }
  13971. IIdAtom * queryPatternName(IHqlExpression * expr)
  13972. {
  13973. if (expr->getOperator() == no_pat_instance)
  13974. return expr->queryChild(1)->queryId();
  13975. return NULL;
  13976. }
  13977. IHqlExpression * createGroupedAttribute(IHqlExpression * grouping)
  13978. {
  13979. return createAttribute(groupedAtom, LINK(grouping));
  13980. }
  13981. IHqlExpression * createTypeTransfer(IHqlExpression * expr, ITypeInfo * _newType)
  13982. {
  13983. Owned<ITypeInfo> newType = _newType;
  13984. switch (newType->getTypeCode())
  13985. {
  13986. case type_row:
  13987. case type_record:
  13988. return createRow(no_typetransfer, LINK(queryOriginalRecord(newType)), expr);
  13989. case type_table:
  13990. case type_groupedtable:
  13991. return createDataset(no_typetransfer, LINK(queryOriginalRecord(newType)), expr);
  13992. case type_dictionary:
  13993. return createDictionary(no_typetransfer, LINK(queryOriginalRecord(newType)), expr);
  13994. default:
  13995. return createValue(no_typetransfer, newType.getClear(), expr);
  13996. }
  13997. }
  13998. //Make sure the expression doesn't get leaked if an exception occurs when closing it.
  13999. IHqlExpression * closeAndLink(IHqlExpression * expr)
  14000. {
  14001. expr->Link();
  14002. try
  14003. {
  14004. return expr->closeExpr();
  14005. }
  14006. catch (...)
  14007. {
  14008. expr->Release();
  14009. throw;
  14010. }
  14011. }
  14012. //MORE: This should probably be handled via the Lookup context instead (which shoudl be renamed parse
  14013. static bool legacyImportMode = false;
  14014. static bool legacyWhenMode = false;
  14015. extern HQL_API void setLegacyEclSemantics(bool _legacyImport, bool _legacyWhen)
  14016. {
  14017. legacyImportMode = _legacyImport;
  14018. legacyWhenMode = _legacyWhen;
  14019. }
  14020. extern HQL_API bool queryLegacyImportSemantics()
  14021. {
  14022. return legacyImportMode;
  14023. }
  14024. extern HQL_API bool queryLegacyWhenSemantics()
  14025. {
  14026. return legacyWhenMode;
  14027. }
  14028. static bool readNumber(unsigned & value, const char * & cur)
  14029. {
  14030. char * end;
  14031. value = (unsigned)strtol(cur, &end, 10);
  14032. if (cur == end)
  14033. return false;
  14034. cur = end;
  14035. return true;
  14036. }
  14037. extern bool HQL_API extractVersion(unsigned & major, unsigned & minor, unsigned & sub, const char * version)
  14038. {
  14039. major = minor = sub = 0;
  14040. if (!version)
  14041. return false;
  14042. if (!readNumber(major, version))
  14043. return false;
  14044. if (*version++ != '.')
  14045. return false;
  14046. if (!readNumber(minor, version))
  14047. return false;
  14048. if (*version++ != '.')
  14049. return false;
  14050. if (!readNumber(sub, version))
  14051. return false;
  14052. return true;
  14053. }
  14054. /*
  14055. List of changes:
  14056. * Rename queryTransformExtra() in transformer class for clarity?
  14057. 1) Make transformStack non linking - it shouldn't be possible for expressions to disappear while a child transform is happening
  14058. 4) Add a HEF2workflow instead of HEF2sandbox, and use for define, globalscope, and workflow optimizations.
  14059. 5) How can I remove the need for temporary classes if no transformations occur?
  14060. E.g., if createTransform() returns same, set extra to expr instead of the appropriate new class.
  14061. More complicated, but would save lots of allocations, linking etc.. How would this be handled without too much pain?
  14062. - flag in the transformer????
  14063. E.g.,Would adding another extra field help remove a temporary class?
  14064. - splitter verifier usecount
  14065. - sharing count in other situations.
  14066. 7) How can I avoid linking the expression on return from createTransformed()?
  14067. - Dangerous.......but potentially good.
  14068. - existing createTransformed() renamed createTransformedEx(), which can return NULL if same.
  14069. - transformEx() instead of transform()
  14070. calls createTransformEx(), returns NULL if already exists, and matches expr.
  14071. - createTransform() and transform() implemented as inline functions that wrap the functions above, and force them to be non-null
  14072. - transformChildren() etc. can call transformEx(), and if there is a difference then need to unwindChildren(expr, start, cur-1)
  14073. 8) When can analysis be simplified to not create the helper classes?
  14074. N) Produce a list of all the transformations that are done - as a useful start to a brown bag talk, and see if any can be short circuited.
  14075. *) What flags can be used to terminate some of the transforms early
  14076. - contains no_setmeta
  14077. */