hqlcpp.cpp 399 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #include "platform.h"
  15. #include <algorithm>
  16. #include "jliball.hpp"
  17. #include "jlib.hpp"
  18. #include "jexcept.hpp"
  19. #include "jmisc.hpp"
  20. #include "javahash.hpp"
  21. #include "jmd5.hpp"
  22. #include "jfile.hpp"
  23. #include "eclhelper.hpp"
  24. #include "hql.hpp"
  25. #include "hqlfunc.hpp"
  26. #include "hqlattr.hpp"
  27. #include "hqlcpp.ipp"
  28. #include "hqlwcpp.hpp"
  29. #include "hqlcpputil.hpp"
  30. #include "hqlres.hpp"
  31. #include "hqlerror.hpp"
  32. #include "hqlcerrors.hpp"
  33. #include "hqlcatom.hpp"
  34. #include "hqlpmap.hpp"
  35. #include "hqlthql.hpp"
  36. #include "hqlfold.hpp"
  37. #include "eclrtl.hpp"
  38. #include "hqllib.ipp"
  39. #include "hqlnlp.ipp"
  40. #include "hqlutil.hpp"
  41. #include "hqltcppc.ipp"
  42. #include "hqlttcpp.ipp"
  43. #include "hqlccommon.hpp"
  44. #include "hqlopt.hpp"
  45. #include "hqlpopt.hpp"
  46. #include "hqlcse.ipp"
  47. #include "thorplugin.hpp"
  48. #include "hqlinline.hpp"
  49. #include "hqlusage.hpp"
  50. #ifdef _DEBUG
  51. //#define ADD_ASSIGNMENT_COMMENTS
  52. //#define ADD_RESOURCE_AS_CPP_COMMENT
  53. #endif
  54. //Defaults for various options.
  55. #define COMPLEXITY_TO_HOIST 2
  56. #define INLINE_COMPARE_THRESHOLD 2 //7 // above this, a loop is generated
  57. #define MAX_NESTED_CASES 8
  58. #define MAX_SIMPLE_VAR_SIZE 99999
  59. #define MAX_STATIC_ROW_SIZE 10000
  60. #define MAX_LOCAL_ROW_SIZE 32
  61. #define DEFAULT_NLP_DETAIL 1
  62. #ifdef _WIN32
  63. #define DEFAULT_ACTIVITIES_PER_CPP 800 // windows compiler is fast, linker is slow, but compiler also has quite a small compile limit
  64. #else
  65. #define DEFAULT_ACTIVITIES_PER_CPP 500 // gcc assembler is v.slow
  66. #endif
  67. //MORE: Simple vars don't work if they are made class members...
  68. //#define SEARCH_VARIABLE "v211"
  69. //===========================================================================
  70. static CriticalSection * systemCS;
  71. static IHqlScope * cppSystemScope;
  72. //===========================================================================
  73. MODULE_INIT(INIT_PRIORITY_STANDARD)
  74. {
  75. systemCS = new CriticalSection;
  76. return true;
  77. }
  78. MODULE_EXIT()
  79. {
  80. ::Release(cppSystemScope);
  81. cppSystemScope = NULL;
  82. delete systemCS;
  83. }
  84. //---------------------------------------------------------------------------
  85. class SubStringInfo : public SubStringHelper
  86. {
  87. public:
  88. SubStringInfo(IHqlExpression * _expr) : SubStringHelper(_expr) { expr = _expr; }
  89. void bindToFrom(HqlCppTranslator & translator, BuildCtx & ctx);
  90. public:
  91. IHqlExpression * expr;
  92. CHqlBoundExpr boundFrom;
  93. CHqlBoundExpr boundTo;
  94. };
  95. void SubStringInfo::bindToFrom(HqlCppTranslator & translator, BuildCtx & ctx)
  96. {
  97. if (to && to->isAttribute())
  98. throwError(HQLERR_StarRangeOnlyInJoinCondition);
  99. if (from == to)
  100. {
  101. if (from)
  102. {
  103. translator.buildSimpleExpr(ctx, from, boundFrom);
  104. boundTo.expr.set(boundFrom.expr);
  105. }
  106. }
  107. else
  108. {
  109. if (from)
  110. translator.buildCachedExpr(ctx, from, boundFrom);
  111. if (to)
  112. translator.buildCachedExpr(ctx, to, boundTo);
  113. }
  114. }
  115. //---------------------------------------------------------------------------
  116. WorkflowItem::WorkflowItem(IHqlExpression * _function) : wfid(0), function(_function)
  117. {
  118. IHqlExpression * body = function->queryChild(0);
  119. assertex(body->getOperator() == no_outofline);
  120. IHqlExpression * ecl = body->queryChild(0);
  121. exprs.append(*createValue(no_return_stmt, makeVoidType(), LINK(ecl)));
  122. }
  123. IHqlExpression * WorkflowItem::getFunction() const
  124. {
  125. IHqlExpression * body = function->queryChild(0);
  126. unsigned max = exprs.ordinality();
  127. assertex(max);
  128. LinkedHqlExpr newecl = exprs.item(max-1).queryChild(0);
  129. for (unsigned i=max-1; i--; )
  130. {
  131. IHqlExpression * cur = &exprs.item(i);
  132. newecl.setown(createCompound(LINK(cur), newecl.getClear()));
  133. }
  134. OwnedHqlExpr newBody = replaceChild(body, 0, newecl);
  135. return replaceChild(function, 0, newBody);
  136. }
  137. //---------------------------------------------------------------------------
  138. IHqlExpression * DatasetReference::querySelector() const
  139. {
  140. if (side == no_none)
  141. return ds->queryNormalizedSelector();
  142. return selector;
  143. }
  144. IHqlExpression * DatasetReference::querySelSeq() const
  145. {
  146. if (side == no_none)
  147. return NULL;
  148. return selector->queryChild(1);
  149. }
  150. IHqlExpression * DatasetReference::mapCompound(IHqlExpression * expr, IHqlExpression * to) const
  151. {
  152. return replaceSelector(expr, querySelector(), to);
  153. }
  154. IHqlExpression * DatasetReference::mapScalar(IHqlExpression * expr, IHqlExpression * to) const
  155. {
  156. return replaceSelector(expr, querySelector(), to);
  157. }
  158. //---------------------------------------------------------------------------
  159. IHqlExpression * createVariable(ITypeInfo * type)
  160. {
  161. StringBuffer tempName;
  162. getUniqueId(tempName.append('v'));
  163. #ifdef _DEBUG
  164. #ifdef SEARCH_VARIABLE
  165. if (stricmp(tempName.str(), SEARCH_VARIABLE)==0)
  166. type = type;
  167. #endif
  168. #endif
  169. return ::createVariable(tempName.str(), type);
  170. }
  171. IHqlExpression * convertWrapperToPointer(IHqlExpression * expr)
  172. {
  173. ITypeInfo * type = expr->queryType();
  174. if (hasWrapperModifier(type))
  175. return createValue(no_implicitcast, makeReferenceModifier(removeModifier(type, typemod_wrapper)), LINK(expr));
  176. return LINK(expr);
  177. }
  178. IHqlExpression * ensureIndexable(IHqlExpression * expr)
  179. {
  180. ITypeInfo * type = expr->queryType();
  181. if (type->getTypeCode() == type_data)
  182. {
  183. IHqlExpression * base = queryStripCasts(expr);
  184. return createValue(no_implicitcast, makeReferenceModifier(makeStringType(type->getSize(), NULL, NULL)), LINK(base));
  185. }
  186. return convertWrapperToPointer(expr);
  187. }
  188. void extendConjunctionOwn(HqlExprAttr & cond, IHqlExpression * next)
  189. {
  190. if (cond)
  191. next = createBoolExpr(no_and, cond.getClear(), next);
  192. cond.setown(next);
  193. }
  194. inline bool isPushed(const IHqlExpression * expr)
  195. {
  196. return (expr->getOperator() == no_decimalstack);
  197. }
  198. inline bool isPushed(const CHqlBoundExpr & bound)
  199. {
  200. return isPushed(bound.expr);
  201. }
  202. bool isSimpleTranslatedStringExpr(IHqlExpression * expr)
  203. {
  204. loop
  205. {
  206. node_operator op = expr->getOperator();
  207. switch (op)
  208. {
  209. case no_constant:
  210. case no_variable:
  211. case no_callback:
  212. return true;
  213. case no_cast:
  214. case no_implicitcast:
  215. case no_typetransfer:
  216. case no_deref:
  217. case no_address:
  218. expr = expr->queryChild(0);
  219. break;
  220. case no_add:
  221. case no_sub:
  222. if (!isSimpleTranslatedStringExpr(expr->queryChild(1)))
  223. return false;
  224. expr = expr->queryChild(0);
  225. break;
  226. default:
  227. return false;
  228. }
  229. }
  230. }
  231. bool isSimpleTranslatedExpr(IHqlExpression * expr)
  232. {
  233. switch (expr->queryType()->getTypeCode())
  234. {
  235. case type_data:
  236. case type_string:
  237. case type_qstring:
  238. case type_varstring:
  239. case type_decimal:
  240. //Less strict rules for strings (and decimal), because string temporaries are more expensive.
  241. return isSimpleTranslatedStringExpr(expr);
  242. case type_set:
  243. //for the moment assume set expressions are always simple once translated.
  244. return true;
  245. }
  246. loop
  247. {
  248. node_operator op = expr->getOperator();
  249. switch (op)
  250. {
  251. case no_constant:
  252. case no_variable:
  253. case no_callback:
  254. case no_nullptr:
  255. return true;
  256. case no_typetransfer:
  257. expr = expr->queryChild(0);
  258. break;
  259. default:
  260. return false;
  261. }
  262. }
  263. }
  264. bool isFixedLengthList(IHqlExpression * expr)
  265. {
  266. switch (expr->getOperator())
  267. {
  268. case no_list:
  269. case no_datasetlist:
  270. case no_sortlist:
  271. return true;
  272. }
  273. return false;
  274. }
  275. bool needVarStringCompare(ITypeInfo * leftType, ITypeInfo * rightType)
  276. {
  277. unsigned lSize = leftType->getSize();
  278. unsigned rSize = rightType->getSize();
  279. return (lSize != rSize) || (lSize == UNKNOWN_LENGTH);
  280. }
  281. _ATOM queryStrCompareFunc(ITypeInfo * realType)
  282. {
  283. switch (realType->getTypeCode())
  284. {
  285. case type_data:
  286. return compareDataDataAtom;
  287. case type_qstring:
  288. return compareQStrQStrAtom;
  289. }
  290. ICharsetInfo * charset = realType->queryCharset();
  291. _ATOM charsetName = charset->queryName();
  292. if (charsetName == dataAtom)
  293. return compareDataDataAtom;
  294. if (charsetName == asciiAtom)
  295. return compareStrStrAtom;
  296. if (charsetName == ebcdicAtom)
  297. return compareEStrEStrAtom;
  298. assertex(!"Unknown string comparison");
  299. return compareStrStrAtom;
  300. }
  301. IHqlExpression * getAddress(IHqlExpression * expr)
  302. {
  303. if (expr->getOperator() == no_deref)
  304. {
  305. IHqlExpression * address = expr->queryChild(0);
  306. return LINK(address);
  307. }
  308. return createValue(no_address, makePointerType(expr->getType()), LINK(expr));
  309. }
  310. IHqlExpression * getRawAddress(IHqlExpression * expr)
  311. {
  312. OwnedHqlExpr raw = getAddress(expr);
  313. loop
  314. {
  315. switch (raw->getOperator())
  316. {
  317. case no_cast:
  318. case no_implicitcast:
  319. break;
  320. default:
  321. return raw.getClear();
  322. }
  323. raw.set(raw->queryChild(0));
  324. }
  325. }
  326. IHqlExpression * getPointer(IHqlExpression * source)
  327. {
  328. if (source->getOperator() == no_constant)
  329. return LINK(source);
  330. ITypeInfo * type = source->queryType();
  331. Owned<ITypeInfo> newType;
  332. switch (type->getTypeCode())
  333. {
  334. case type_set:
  335. if (type->isReference())
  336. return LINK(source);
  337. newType.setown(makeReferenceModifier(LINK(queryUnqualifiedType(type))));
  338. if (hasWrapperModifier(type))
  339. {
  340. OwnedHqlExpr cast = createValue(no_implicitcast, LINK(newType), LINK(source));
  341. return createValue(no_typetransfer, LINK(newType), LINK(cast));
  342. }
  343. break;
  344. case type_table:
  345. case type_groupedtable:
  346. case type_row:
  347. case type_decimal:
  348. case type_string:
  349. case type_data:
  350. case type_qstring:
  351. case type_varstring:
  352. case type_unicode:
  353. case type_varunicode:
  354. case type_utf8:
  355. if (isTypePassedByAddress(type))
  356. {
  357. if (type->isReference())
  358. return LINK(source);
  359. newType.setown(makeReferenceModifier(LINK(queryUnqualifiedType(type))));
  360. if (hasLinkCountedModifier(type))
  361. newType.setown(makeAttributeModifier(newType.getClear(), getLinkCountedAttr()));
  362. if (hasWrapperModifier(type))
  363. return createValue(no_implicitcast, LINK(newType), LINK(source));
  364. //An array of X is implicitly converted to pointer to X so no need to do &a[0]
  365. return createValue(no_typetransfer, LINK(newType), LINK(source));
  366. }
  367. else
  368. {
  369. newType.setown(removeModifier(type, typemod_wrapper));
  370. if (hasWrapperModifier(type))
  371. return createValue(no_implicitcast, LINK(newType), LINK(source));
  372. return LINK(source);
  373. }
  374. break;
  375. case type_pointer:
  376. return LINK(source);
  377. default:
  378. newType.setown(makePointerType(LINK(type)));
  379. break;
  380. }
  381. IHqlExpression * cur = source;
  382. while (cur->getOperator() == no_typetransfer)
  383. cur = cur->queryChild(0);
  384. if (cur->getOperator() == no_deref)
  385. {
  386. IHqlExpression * address = cur->queryChild(0);
  387. if (address->queryType() == newType)
  388. return LINK(address);
  389. return createValue(no_implicitcast, newType.getClear(), LINK(address));
  390. }
  391. else
  392. return createValue(no_address, newType.getClear(), LINK(source));
  393. }
  394. bool isChildOf(IHqlExpression * parent, IHqlExpression * child)
  395. {
  396. unsigned max = parent->numChildren();
  397. unsigned idx;
  398. for (idx = 0; idx < max; idx++)
  399. {
  400. IHqlExpression * cur = parent->queryChild(idx);
  401. if (cur == child)
  402. return true;
  403. }
  404. return false;
  405. }
  406. bool canRemoveStringCast(ITypeInfo * to, ITypeInfo * from)
  407. {
  408. unsigned fromSize = from->getSize();
  409. unsigned toSize = to->getSize();
  410. //Special case string conversions that don't require us to copy any data.
  411. if ((toSize == UNKNOWN_LENGTH) || ((fromSize != UNKNOWN_LENGTH) && (toSize <= fromSize)))
  412. {
  413. switch (from->getTypeCode())
  414. {
  415. case type_varstring:
  416. if (toSize != UNKNOWN_LENGTH)
  417. break;
  418. //fall through
  419. case type_data:
  420. case type_string:
  421. {
  422. ICharsetInfo * srcset = from->queryCharset();
  423. ICharsetInfo * tgtset = to->queryCharset();
  424. //Data never calls a conversion function...
  425. if ((srcset == tgtset) || (to->getTypeCode() == type_data) || (from->getTypeCode() == type_data))
  426. return true;
  427. }
  428. case type_qstring:
  429. return false;
  430. }
  431. }
  432. return false;
  433. }
  434. bool isProjectedInRecord(IHqlExpression * record, IHqlExpression * expr)
  435. {
  436. unsigned max = record->numChildren();
  437. unsigned idx;
  438. for (idx = 0; idx < max; idx++)
  439. {
  440. IHqlExpression * cur = record->queryChild(idx);
  441. if (cur->queryChild(0) == expr)
  442. return true;
  443. }
  444. return false;
  445. }
  446. IHqlExpression * queryStripCasts(IHqlExpression * expr)
  447. {
  448. while ((expr->getOperator() == no_cast) || (expr->getOperator() == no_implicitcast))
  449. expr = expr->queryChild(0);
  450. return expr;
  451. }
  452. // Format the list is stored in doesn't matter, so allow constant strings to be stored by reference
  453. IHqlExpression * getOptimialListFormat(IHqlExpression * table)
  454. {
  455. if (table->isConstant() && table->getOperator() == no_list)
  456. {
  457. ITypeInfo * elemType = table->queryType()->queryChildType();
  458. if (!elemType->isReference())
  459. {
  460. switch (elemType->getTypeCode())
  461. {
  462. case type_string:
  463. case type_data:
  464. {
  465. HqlExprArray args;
  466. table->unwindList(args, no_list);
  467. return createValue(no_list, makeSetType(makeReferenceModifier(LINK(elemType))), args);
  468. }
  469. }
  470. }
  471. }
  472. return LINK(table);
  473. }
  474. bool canOptimizeAdjust(IHqlExpression * value)
  475. {
  476. ITypeInfo * type = value->queryType();
  477. switch (value->getOperator())
  478. {
  479. case no_constant:
  480. return true;
  481. case no_add:
  482. case no_sub:
  483. return value->queryChild(1)->queryValue() != NULL;
  484. }
  485. return false;
  486. }
  487. IHqlExpression * adjustValue(IHqlExpression * value, __int64 delta)
  488. {
  489. if (delta == 0)
  490. return LINK(value);
  491. ITypeInfo * type = value->queryType();
  492. switch (value->getOperator())
  493. {
  494. case no_constant:
  495. {
  496. __int64 newValue = value->queryValue()->getIntValue()+delta;
  497. if (type == sizetType)
  498. return getSizetConstant((size32_t)newValue);
  499. return createConstant(type->castFrom(true, newValue));
  500. }
  501. case no_add:
  502. {
  503. IHqlExpression * lhs = value->queryChild(0);
  504. IHqlExpression * rhs = value->queryChild(1);
  505. IValue * rhsValue = rhs->queryValue();
  506. IValue * lhsValue = lhs->queryValue();
  507. if (rhsValue)
  508. {
  509. delta += rhsValue->getIntValue();
  510. if (delta == 0)
  511. return LINK(lhs);
  512. value = lhs;
  513. }
  514. else if (lhsValue)
  515. {
  516. delta += lhsValue->getIntValue();
  517. if (delta == 0)
  518. return LINK(rhs);
  519. value = rhs;
  520. }
  521. else if (canOptimizeAdjust(rhs))
  522. return createValue(no_add, value->getType(), LINK(lhs), adjustValue(rhs, delta));
  523. break;
  524. }
  525. case no_sub:
  526. {
  527. IValue * rhsValue = value->queryChild(1)->queryValue();
  528. if (rhsValue)
  529. {
  530. IHqlExpression * lhs = value->queryChild(0);
  531. delta -= rhsValue->getIntValue();
  532. if (delta == 0)
  533. return LINK(lhs);
  534. value = lhs;
  535. }
  536. break;
  537. }
  538. case no_translated:
  539. {
  540. IHqlExpression * arg = value->queryChild(0);
  541. if (arg->queryValue())
  542. {
  543. OwnedHqlExpr newValue = adjustValue(arg, delta);
  544. return createTranslated(newValue);
  545. }
  546. break;
  547. }
  548. }
  549. IHqlExpression * deltaExpr;
  550. node_operator op = no_add;
  551. if (delta < 0)
  552. {
  553. op = no_sub;
  554. delta = -delta;
  555. }
  556. if (type == sizetType || !type->isInteger())
  557. deltaExpr = getSizetConstant((size32_t)delta);
  558. else
  559. deltaExpr = createConstant(type->castFrom(true, delta));
  560. return createValue(op, LINK(type), LINK(value), deltaExpr);
  561. }
  562. IHqlExpression * adjustIndexBaseToZero(IHqlExpression * index)
  563. {
  564. return adjustValue(index, -1);
  565. }
  566. IHqlExpression * adjustIndexBaseToOne(IHqlExpression * index)
  567. {
  568. return adjustValue(index, +1);
  569. }
  570. IHqlExpression * adjustBoundIntegerValues(IHqlExpression * left, IHqlExpression * right, bool subtract)
  571. {
  572. assertex(queryUnqualifiedType(left->queryType()) == queryUnqualifiedType(right->queryType()));
  573. if (canOptimizeAdjust(left))
  574. {
  575. node_operator op = right->getOperator();
  576. switch (op)
  577. {
  578. case no_constant:
  579. {
  580. __int64 rhsValue = right->queryValue()->getIntValue();
  581. if (subtract)
  582. rhsValue = -rhsValue;
  583. return adjustValue(left, rhsValue);
  584. }
  585. case no_add:
  586. case no_sub:
  587. {
  588. IHqlExpression * rl = right->queryChild(0);
  589. IHqlExpression * rr = right->queryChild(1);
  590. if (rr->getOperator() == no_constant)
  591. {
  592. ITypeInfo * rlt = rl->queryType();
  593. ITypeInfo * rrt = rr->queryType();
  594. if (queryUnqualifiedType(rl->queryType()) == queryUnqualifiedType(rr->queryType()))
  595. {
  596. __int64 delta = rr->queryValue()->getIntValue();
  597. if (op == no_sub)
  598. delta = -delta;
  599. if (subtract)
  600. delta = -delta;
  601. OwnedHqlExpr newLeft = adjustValue(left, delta);
  602. return adjustBoundIntegerValues(newLeft, rl, subtract);
  603. }
  604. }
  605. break;
  606. }
  607. }
  608. }
  609. switch (left->getOperator())
  610. {
  611. case no_constant:
  612. if (!subtract)
  613. return adjustBoundIntegerValues(right, left, false);
  614. break;
  615. case no_add:
  616. {
  617. IHqlExpression * lr = left->queryChild(1);
  618. if (lr->getOperator() == no_constant)
  619. {
  620. OwnedHqlExpr newLeft = adjustBoundIntegerValues(left->queryChild(0), right, subtract);
  621. return adjustBoundIntegerValues(newLeft, lr, false);
  622. }
  623. break;
  624. }
  625. case no_variable:
  626. if (!subtract && (right->getOperator() == no_add) && (right->queryChild(1)->getOperator() == no_constant))
  627. {
  628. OwnedHqlExpr temp = adjustBoundIntegerValues(left, right->queryChild(0), false);
  629. return adjustBoundIntegerValues(temp, right->queryChild(1), false);
  630. }
  631. break;
  632. }
  633. return createValue(subtract ? no_sub : no_add, left->getType(), LINK(left), LINK(right));
  634. }
  635. IHqlExpression * multiplyValue(IHqlExpression * expr, unsigned __int64 value)
  636. {
  637. if (isZero(expr))
  638. return LINK(expr);
  639. ITypeInfo * type = expr->queryType();
  640. IValue * exprValue = expr->queryValue();
  641. if (exprValue && type->isInteger())
  642. return createConstant(type->castFrom(false, exprValue->getIntValue() * value));
  643. if (expr->getOperator() == no_translated)
  644. {
  645. IHqlExpression * translated = expr->queryChild(0);
  646. if (translated->queryValue())
  647. {
  648. OwnedHqlExpr newValue = multiplyValue(translated, value);
  649. return createTranslated(newValue);
  650. }
  651. }
  652. return createValue(no_mul, LINK(type), LINK(expr), createConstant(type->castFrom(false, value)));
  653. }
  654. bool matchesConstValue(IHqlExpression * expr, __int64 matchValue)
  655. {
  656. IValue * value = expr->queryValue();
  657. if (value)
  658. return value->getIntValue() == matchValue;
  659. if (expr->getOperator() == no_translated)
  660. return matchesConstValue(expr->queryChild(0), matchValue);
  661. return false;
  662. }
  663. IHqlExpression * createTranslated(IHqlExpression * expr)
  664. {
  665. return createValue(no_translated, expr->getType(), LINK(expr));
  666. }
  667. IHqlExpression * createTranslatedOwned(IHqlExpression * expr)
  668. {
  669. return createValue(no_translated, expr->getType(), expr);
  670. }
  671. IHqlExpression * createTranslated(IHqlExpression * expr, IHqlExpression * length)
  672. {
  673. ITypeInfo * type = expr->queryType();
  674. switch (type->getTypeCode())
  675. {
  676. case type_table:
  677. case type_groupedtable:
  678. return createDataset(no_translated, LINK(expr), LINK(length));
  679. }
  680. return createValue(no_translated, expr->getType(), LINK(expr), LINK(length));
  681. }
  682. static IHqlExpression * querySimplifyCompareArgCast(IHqlExpression * expr)
  683. {
  684. if (expr->isConstant())
  685. return expr;
  686. while ((expr->getOperator() == no_implicitcast) || (expr->getOperator() == no_cast))
  687. {
  688. ITypeInfo * type = expr->queryType()->queryPromotedType();
  689. switch (type->getTypeCode())
  690. {
  691. case type_string:
  692. case type_data:
  693. case type_unicode:
  694. case type_qstring:
  695. case type_utf8:
  696. break;
  697. default:
  698. return expr;
  699. }
  700. IHqlExpression * child = expr->queryChild(0);
  701. ITypeInfo * childType = child->queryType()->queryPromotedType();
  702. if (type->getStringLen() < childType->getStringLen())
  703. break;
  704. type_t tc = type->getTypeCode();
  705. if (tc != childType->getTypeCode())
  706. {
  707. if (tc == type_string)
  708. {
  709. if (childType->getTypeCode() != type_varstring)
  710. break;
  711. if (type->queryCharset() != childType->queryCharset())
  712. break;
  713. }
  714. else if (tc == type_unicode)
  715. {
  716. if (childType->getTypeCode() != type_varunicode)
  717. break;
  718. if (type->queryLocale() != childType->queryLocale())
  719. break;
  720. }
  721. else
  722. break;
  723. }
  724. else
  725. {
  726. Owned<ITypeInfo> stretched = getStretchedType(type->getStringLen(), childType);
  727. if (stretched != type)
  728. break;
  729. }
  730. expr = child;
  731. }
  732. return expr;
  733. }
  734. IHqlExpression * getSimplifyCompareArg(IHqlExpression * expr)
  735. {
  736. IHqlExpression * cast = querySimplifyCompareArgCast(expr);
  737. if (cast->getOperator() != no_substring)
  738. return LINK(cast);
  739. if (cast->queryChild(0)->queryType()->getTypeCode() == type_qstring)
  740. return LINK(cast);
  741. HqlExprArray args;
  742. unwindChildren(args, cast);
  743. args.append(*createAttribute(quickAtom));
  744. return cast->clone(args);
  745. }
  746. bool isNullAssign(const CHqlBoundTarget & target, IHqlExpression * expr)
  747. {
  748. ITypeInfo * targetType = target.expr->queryType();
  749. //if an assignment to a local variable size temporary object, then it is ok to omit an assignment of null
  750. //since it won't change its value, and it isn't going to be assigned more than once.
  751. if ((targetType->getSize() == UNKNOWN_LENGTH) && target.length && hasWrapperModifier(targetType) && !hasModifier(targetType, typemod_member))
  752. {
  753. ITypeInfo * exprType = expr->queryType();
  754. switch (exprType->getTypeCode())
  755. {
  756. case type_data:
  757. case type_string:
  758. case type_qstring:
  759. return exprType->getSize() == 0;
  760. case type_table:
  761. return expr->getOperator() == no_null;
  762. }
  763. }
  764. return false;
  765. }
  766. ExpressionFormat queryNaturalFormat(ITypeInfo * type)
  767. {
  768. if (hasOutOfLineModifier(type))
  769. return FormatArrayDataset;
  770. if (hasLinkCountedModifier(type))
  771. return FormatLinkedDataset;
  772. return FormatBlockedDataset;
  773. }
  774. //===========================================================================
  775. SubGraphInfo::SubGraphInfo(IPropertyTree * _tree, unsigned _id, IHqlExpression * _graphTag, SubGraphType _type)
  776. : HqlExprAssociation(subGraphMarker), tree(_tree)
  777. {
  778. id = _id;
  779. type = _type;
  780. graphTag.set(_graphTag);
  781. }
  782. //===========================================================================
  783. IHqlExpression * CHqlBoundExpr::getTranslatedExpr() const
  784. {
  785. HqlExprArray args;
  786. args.append(*LINK(expr));
  787. if (length) args.append(*LINK(length));
  788. if (count) args.append(*createAttribute(countAtom, LINK(count)));
  789. if (isAll) args.append(*createAttribute(allAtom, LINK(isAll)));
  790. ITypeInfo * type = expr->queryType();
  791. switch (type->getTypeCode())
  792. {
  793. case type_table:
  794. case type_groupedtable:
  795. return createDataset(no_translated, args);
  796. }
  797. return createValue(no_translated, LINK(type), args);
  798. }
  799. IHqlExpression * CHqlBoundExpr::getIsAll() const
  800. {
  801. if (isAll)
  802. return LINK(isAll);
  803. return LINK(queryBoolExpr(false));
  804. }
  805. void CHqlBoundExpr::setFromTarget(const CHqlBoundTarget & target)
  806. {
  807. isAll.set(target.isAll);
  808. count.set(target.count);
  809. length.set(target.length);
  810. expr.setown(convertWrapperToPointer(target.expr));
  811. }
  812. void CHqlBoundExpr::setFromTranslated(IHqlExpression * translatedExpr)
  813. {
  814. expr.set(translatedExpr->queryChild(0));
  815. IHqlExpression * arg = translatedExpr->queryChild(1);
  816. if (arg)
  817. {
  818. unsigned i = 2;
  819. if (arg->getOperator() != no_attr)
  820. {
  821. length.set(arg);
  822. arg = translatedExpr->queryChild(i++);
  823. }
  824. while (arg)
  825. {
  826. _ATOM name = arg->queryName();
  827. if (name == countAtom)
  828. count.set(arg->queryChild(0));
  829. else if (name == allAtom)
  830. isAll.set(arg->queryChild(0));
  831. else
  832. UNIMPLEMENTED;
  833. arg = translatedExpr->queryChild(i++);
  834. }
  835. }
  836. }
  837. bool CHqlBoundTarget::extractFrom(const CHqlBoundExpr & bound)
  838. {
  839. ITypeInfo * boundType = bound.queryType();
  840. if (bound.count)
  841. {
  842. if (bound.count->getOperator() != no_variable)
  843. return false;
  844. if (!hasLinkCountedModifier(boundType))
  845. return false;
  846. }
  847. if (bound.isAll)
  848. {
  849. assertex(bound.isAll->getOperator() == no_variable);
  850. }
  851. else if (boundType->getTypeCode() == type_set)
  852. return false;
  853. if (bound.length)
  854. {
  855. if (bound.length->getOperator() != no_variable)
  856. return false;
  857. }
  858. else if (boundType->getSize() == UNKNOWN_LENGTH)
  859. {
  860. type_t btc = boundType->getTypeCode();
  861. if ((btc != type_varstring) && (btc != type_varunicode) && !hasLinkCountedModifier(boundType))
  862. return false;
  863. }
  864. IHqlExpression * boundExpr = bound.expr;
  865. if (boundExpr->getOperator() == no_implicitcast)
  866. {
  867. IHqlExpression * uncast = boundExpr->queryChild(0);
  868. if (hasModifier(uncast->queryType(), typemod_member) &&
  869. (queryUnqualifiedType(boundExpr->queryType()) == queryUnqualifiedType(uncast->queryType())))
  870. boundExpr = uncast;
  871. }
  872. expr.set(boundExpr);
  873. isAll.set(bound.isAll);
  874. length.set(bound.length);
  875. count.set(bound.count);
  876. return true;
  877. }
  878. bool CHqlBoundTarget::isFixedSize() const
  879. {
  880. validate();
  881. return queryType()->getSize() != UNKNOWN_LENGTH;
  882. }
  883. void CHqlBoundTarget::validate() const
  884. {
  885. if (expr)
  886. {
  887. if (queryType()->getSize() != UNKNOWN_LENGTH)
  888. {
  889. assertex(!length);
  890. }
  891. else if (isArrayRowset(queryType()))
  892. assertex(count != NULL);
  893. else
  894. {
  895. assertex(length || queryType()->getTypeCode() == type_varstring || queryType()->getTypeCode() == type_varunicode);
  896. }
  897. }
  898. }
  899. ITypeInfo * CHqlBoundTarget::queryType() const
  900. {
  901. return expr->queryType();
  902. }
  903. IHqlExpression * CHqlBoundTarget::getTranslatedExpr() const
  904. {
  905. CHqlBoundExpr temp;
  906. temp.setFromTarget(*this);
  907. return temp.getTranslatedExpr();
  908. }
  909. //===========================================================================
  910. CompoundBuilder::CompoundBuilder(node_operator _op)
  911. {
  912. op = _op;
  913. }
  914. void CompoundBuilder::addOperand(IHqlExpression * arg)
  915. {
  916. if (first.get())
  917. {
  918. compound.setown(createOpenValue(op, makeBoolType()));
  919. compound->addOperand(first.getClear());
  920. }
  921. if (compound)
  922. compound->addOperand(arg);
  923. else
  924. first.setown(arg);
  925. }
  926. IHqlExpression * CompoundBuilder::getCompound()
  927. {
  928. if (compound)
  929. return compound.getClear()->closeExpr();
  930. return first.getClear();
  931. }
  932. //===========================================================================
  933. void buildClearPointer(BuildCtx & ctx, IHqlExpression * expr, CompilerType compiler)
  934. {
  935. StringBuffer s;
  936. generateExprCpp(s, expr, compiler).append("=NULL;");
  937. ctx.addQuoted(s);
  938. }
  939. void insertUniqueString(StringAttrArray & array, const char * text)
  940. {
  941. ForEachItemIn(idx, array)
  942. {
  943. StringAttrItem & cur = array.item(idx);
  944. if (stricmp(cur.text, text) == 0)
  945. return;
  946. }
  947. array.append(* new StringAttrItem(text));
  948. }
  949. HqlCppInstance::HqlCppInstance(IWorkUnit *_wu, const char * _wupathname)
  950. {
  951. workunit.set(_wu);
  952. wupathname.set(_wupathname);
  953. }
  954. HqlStmts * HqlCppInstance::ensureSection(_ATOM section)
  955. {
  956. HqlStmts * match = querySection(section);
  957. if (match)
  958. return match;
  959. HqlCppSection * cur = new HqlCppSection;
  960. cur->section = section;
  961. sections.append(*cur);
  962. return &cur->stmts;
  963. }
  964. void HqlCppInstance::processIncludes()
  965. {
  966. BuildCtx ctx(*this, includeAtom);
  967. StringBuffer s;
  968. ForEachItemIn(idx, includes)
  969. {
  970. s.clear().append("#include \"").append(includes.item(idx).text).append("\"");
  971. ctx.addQuoted(s);
  972. }
  973. }
  974. const char * HqlCppInstance::queryLibrary(unsigned idx)
  975. {
  976. if (modules.isItem(idx))
  977. return modules.item(idx).text;
  978. return NULL;
  979. }
  980. HqlStmts * HqlCppInstance::querySection(_ATOM section)
  981. {
  982. ForEachItemIn(idx, sections)
  983. {
  984. HqlCppSection & cur = (HqlCppSection &)sections.item(idx);
  985. if (cur.section == section)
  986. return &cur.stmts;
  987. }
  988. return NULL;
  989. }
  990. void HqlCppInstance::addPlugin(const char *plugin, const char *version, bool inThor)
  991. {
  992. if (!plugin || !*plugin)
  993. return;
  994. StringBuffer dllname(plugin);
  995. getFileNameOnly(dllname, false); // MORE - shouldn't really need to do this here....
  996. if (workunit)
  997. {
  998. Owned<IWUPlugin> p = workunit->updatePluginByName(dllname.str());
  999. p->setPluginVersion(version);
  1000. if (inThor)
  1001. p->setPluginThor(true);
  1002. else
  1003. p->setPluginHole(true);
  1004. }
  1005. if (!plugins)
  1006. plugins.setown(createPTree("Plugins"));
  1007. StringBuffer xpath;
  1008. xpath.append("Plugin[@dll='").append(dllname).append("']");
  1009. if (!plugins->hasProp(xpath.str()))
  1010. {
  1011. IPropertyTree * pluginNode = createPTree("Plugin");
  1012. pluginNode->setProp("@dll", dllname.str());
  1013. pluginNode->setProp("@version", version);
  1014. plugins->addPropTree("Plugin", pluginNode);
  1015. }
  1016. }
  1017. void HqlCppInstance::addPluginsAsResource()
  1018. {
  1019. if (!plugins)
  1020. return;
  1021. StringBuffer pluginXML;
  1022. toXML(plugins, pluginXML);
  1023. addResource("PLUGINS", pluginXML.length(), pluginXML.str(), NULL, 1);
  1024. }
  1025. bool HqlCppInstance::useFunction(IHqlExpression * func)
  1026. {
  1027. assertex(func);
  1028. func = func->queryBody();
  1029. if (helpers.contains(*func))
  1030. return false;
  1031. helpers.append(*LINK(func));
  1032. IHqlExpression * funcDef = func->queryChild(0);
  1033. StringBuffer libname, init, include;
  1034. getProperty(funcDef, libraryAtom, libname);
  1035. getProperty(funcDef, initfunctionAtom, init);
  1036. getProperty(funcDef, includeAtom, include);
  1037. if (init.length())
  1038. {
  1039. BuildCtx ctx(*this, initAtom);
  1040. ctx.addQuoted(init.append("(wuid);"));
  1041. }
  1042. IHqlExpression *pluginAttr = funcDef->queryProperty(pluginAtom);
  1043. if (pluginAttr)
  1044. {
  1045. StringBuffer plugin, version;
  1046. getStringValue(plugin, pluginAttr->queryChild(0));
  1047. getStringValue(version, pluginAttr->queryChild(1));
  1048. addPlugin(plugin.str(), version.str(), false);
  1049. if (!libname.length())
  1050. {
  1051. getStringValue(libname, pluginAttr->queryChild(0));
  1052. getFullFileName(libname, true);
  1053. }
  1054. }
  1055. if (!funcDef->hasProperty(ctxmethodAtom) && !funcDef->hasProperty(gctxmethodAtom) && !funcDef->hasProperty(methodAtom))
  1056. {
  1057. if (libname.length())
  1058. useLibrary(libname.str());
  1059. }
  1060. if (include.length())
  1061. useInclude(include.str());
  1062. return true;
  1063. }
  1064. void HqlCppInstance::useInclude(const char * include)
  1065. {
  1066. insertUniqueString(includes, include);
  1067. }
  1068. void HqlCppInstance::useLibrary(const char * libname)
  1069. {
  1070. insertUniqueString(modules, libname);
  1071. }
  1072. void HqlCppInstance::addHint(const char * hintXml, ICodegenContextCallback * ctxCallback)
  1073. {
  1074. if (!hintFile)
  1075. {
  1076. StringBuffer hintFilename;
  1077. if (wupathname)
  1078. hintFilename.append(wupathname);
  1079. else
  1080. hintFilename.append("wu");
  1081. hintFilename.append("_hints.xml");
  1082. Owned<IFile> file = createIFile(hintFilename);
  1083. Owned<IFileIO> io = file->open(IFOcreate);
  1084. if (!io)
  1085. return;
  1086. hintFile.setown(createIOStream(io));
  1087. appendHintText("<Hints>\n");
  1088. Owned<IWUQuery> query = workunit->updateQuery();
  1089. associateLocalFile(query, FileTypeCpp, hintFilename.str(), "Hints", 0);
  1090. ctxCallback->registerFile(hintFilename.str(), "Hints");
  1091. }
  1092. appendHintText(hintXml);
  1093. }
  1094. void HqlCppInstance::appendHintText(const char * xml)
  1095. {
  1096. hintFile->write(strlen(xml), xml);
  1097. }
  1098. unsigned HqlCppInstance::addStringResource(unsigned len, const char * body)
  1099. {
  1100. return resources.addString(len, body);
  1101. }
  1102. void HqlCppInstance::addResource(const char * type, unsigned len, const void * body, IPropertyTree *manifestEntry, unsigned id)
  1103. {
  1104. resources.addNamed(type, len, body, manifestEntry, id);
  1105. }
  1106. void HqlCppInstance::addCompressResource(const char * type, unsigned len, const void * body, IPropertyTree *manifestEntry, unsigned id)
  1107. {
  1108. #ifdef ADD_RESOURCE_AS_CPP_COMMENT
  1109. BuildCtx ctx(*this, includeAtom);
  1110. StringBuffer s;
  1111. s.append("/* ").append(type).append(".").append(id).append(":\n").append(len,(const char *)data).newline().append("*/");
  1112. ctx.addQuoted(s);
  1113. #endif
  1114. resources.addCompress(type, len, body, manifestEntry, id);
  1115. }
  1116. void HqlCppInstance::flushHints()
  1117. {
  1118. if (hintFile)
  1119. {
  1120. appendHintText("</Hints>\n");
  1121. hintFile.clear();
  1122. }
  1123. }
  1124. void HqlCppInstance::flushResources(const char *filename, ICodegenContextCallback * ctxCallback)
  1125. {
  1126. addPluginsAsResource();
  1127. if (resources.count())
  1128. {
  1129. bool flushText = workunit->getDebugValueBool("flushResourceAsText", false);
  1130. StringBuffer path, trailing;
  1131. splitFilename(filename, &path, &path, &trailing, &trailing);
  1132. StringBuffer ln;
  1133. ln.append(path).append(SharedObjectPrefix).append(trailing).append(LibraryExtension);
  1134. #ifdef __64BIT__
  1135. bool target64bit = workunit->getDebugValueBool("target64bit", true);
  1136. #else
  1137. bool target64bit = workunit->getDebugValueBool("target64bit", false);
  1138. #endif
  1139. resources.flush(ln.str(), flushText, target64bit);
  1140. StringBuffer resTextName;
  1141. if (flushText && resources.queryWriteText(resTextName, ln))
  1142. {
  1143. Owned<IWUQuery> query = workunit->updateQuery();
  1144. associateLocalFile(query, FileTypeHintXml, resTextName, "Workunit resource text", 0);
  1145. ctxCallback->registerFile(resTextName, "Workunit Res.txt");
  1146. }
  1147. useLibrary(filename);
  1148. }
  1149. }
  1150. IHqlCppInstance * createCppInstance(IWorkUnit *wu, const char * wupathname)
  1151. {
  1152. return new HqlCppInstance(wu, wupathname);
  1153. }
  1154. //===========================================================================
  1155. #include "hqlcppsys.ecl"
  1156. HqlCppTranslator::HqlCppTranslator(IErrorReceiver * _errors, const char * _soName, IHqlCppInstance * _code, ClusterType _targetClusterType, ICodegenContextCallback *_ctxCallback) : ctxCallback(_ctxCallback)
  1157. {
  1158. targetClusterType = _targetClusterType;
  1159. {
  1160. CriticalBlock block(*systemCS);
  1161. if (!cppSystemScope)
  1162. {
  1163. StringBuffer systemText;
  1164. unsigned size = 0;
  1165. for (unsigned i1=0; cppSystemText[i1]; i1++)
  1166. size += strlen(cppSystemText[i1]) + 2;
  1167. systemText.ensureCapacity(size);
  1168. for (unsigned i2=0; cppSystemText[i2]; i2++)
  1169. systemText.append(cppSystemText[i2]).newline();
  1170. MultiErrorReceiver errs;
  1171. HqlDummyLookupContext ctx(&errs);
  1172. cppSystemScope = createScope();
  1173. Owned<ISourcePath> sysPath = createSourcePath("<system-definitions>");
  1174. Owned<IFileContents> systemContents = createFileContentsFromText(systemText.str(), sysPath);
  1175. OwnedHqlExpr query = parseQuery(cppSystemScope, systemContents, ctx, NULL, false);
  1176. if (errs.errCount())
  1177. {
  1178. StringBuffer errtext;
  1179. IECLError *first = errs.firstError();
  1180. first->toString(errtext);
  1181. throw MakeStringException(HQLERR_FailedToLoadSystemModule, "%s @ %d:%d", errtext.str(), first->getColumn(), first->getLine());
  1182. }
  1183. #if 0
  1184. else if (errs.warnCount())
  1185. {
  1186. StringBuffer s;
  1187. errs.toString(s);
  1188. PrintLog("Parsing system scope: ");
  1189. PrintLog(s.str());
  1190. }
  1191. #endif
  1192. }
  1193. }
  1194. errors = _errors;
  1195. hints = 0;
  1196. litno = 0;
  1197. soName.set(_soName);
  1198. HqlDummyLookupContext dummyctx(NULL);
  1199. OwnedHqlExpr internalScopeLookup = cppSystemScope->lookupSymbol(createIdentifierAtom("InternalCppService"), LSFsharedOK, dummyctx);
  1200. internalScope = internalScopeLookup->queryScope();
  1201. _clear(options); // init options is called later, but depends on the workunit.
  1202. startCursorSet = 0;
  1203. requireTable = true;
  1204. activeGraphCtx = NULL;
  1205. maxSequence = 0;
  1206. contextAvailable = true;
  1207. graphSeqNumber = 0;
  1208. nlpParse = NULL;
  1209. outputLibrary = NULL;
  1210. checkedEmbeddedCpp = false;
  1211. cachedAllowEmbeddedCpp = true;
  1212. checkedPipeAllowed = false;
  1213. activitiesThisCpp = 0;
  1214. curCppFile = 0;
  1215. timeReporter.setown(createStdTimeReporter());
  1216. curActivityId = 0;
  1217. holeUniqueSequence = 0;
  1218. nextUid = 0;
  1219. nextTypeId = 0;
  1220. nextFieldId = 0;
  1221. code = (HqlCppInstance*)_code;
  1222. }
  1223. HqlCppTranslator::~HqlCppTranslator()
  1224. {
  1225. ::Release(nlpParse);
  1226. ::Release(outputLibrary);
  1227. }
  1228. void HqlCppTranslator::setTargetClusterType(ClusterType clusterType)
  1229. {
  1230. targetClusterType = clusterType;
  1231. }
  1232. void HqlCppTranslator::checkAbort()
  1233. {
  1234. if (wu() && wu()->aborting())
  1235. throw MakeStringException(HQLERR_ErrorAlreadyReported, "Aborting");
  1236. }
  1237. // Option: (Name, value, ?overridden, default())
  1238. // problems:
  1239. // default value can depend on another option (e.g., cluster type/supports lcr).
  1240. // don't want code in multiple places - e.g., the values initialized and defaulted, and dependencies calculations duplicated separately.
  1241. // don't want lots of start up costs each time the translator is created -> lightweight classes if any.
  1242. // don't really want two structures, one for the definitions, and another for the values.
  1243. //RESOLVED? want to walk the debug options provided, instead of checking for each possibility in turn.
  1244. // Without this restriction it becomes much easier.
  1245. void HqlCppTranslator::cacheOptions()
  1246. {
  1247. SCMStringBuffer targetText;
  1248. wu()->getDebugValue("targetClusterType", targetText);
  1249. ClusterType clusterType = getClusterType(targetText.s.str());
  1250. if (clusterType != NoCluster)
  1251. setTargetClusterType(clusterType);
  1252. //Some compound flags, which provide defaults for various other options.
  1253. bool paranoid = getDebugFlag("paranoid", false);
  1254. bool releaseMode = getDebugFlag("release", true);
  1255. struct DebugOption
  1256. {
  1257. typedef enum { typeByte, typeUnsigned, typeBool } OptionType;
  1258. DebugOption (bool & _option, const char * name, bool defaultValue) : option(&_option), optName(name)
  1259. {
  1260. _option = defaultValue;
  1261. type = typeBool;
  1262. }
  1263. DebugOption (byte & _option, const char * name, byte defaultValue) : option(&_option), optName(name)
  1264. {
  1265. _option = defaultValue;
  1266. type = typeByte;
  1267. }
  1268. DebugOption (unsigned & _option, const char * name, unsigned defaultValue) : option(&_option), optName(name)
  1269. {
  1270. _option = defaultValue;
  1271. type = typeUnsigned;
  1272. };
  1273. void setValue(const char * val)
  1274. {
  1275. switch (type)
  1276. {
  1277. case typeBool:
  1278. {
  1279. bool * b = (bool*)option;
  1280. *b = strToBool(val);
  1281. break;
  1282. }
  1283. case typeUnsigned:
  1284. {
  1285. unsigned * u = (unsigned*)option;
  1286. *u = (unsigned)atoi(val);
  1287. break;
  1288. }
  1289. case typeByte:
  1290. {
  1291. byte * b = (byte*)option;
  1292. *b = (byte)atoi(val);
  1293. break;
  1294. }
  1295. }
  1296. }
  1297. void * option;
  1298. const char * optName;
  1299. OptionType type;
  1300. };
  1301. //Note this list cannot have any initial values which are dependent on other options.
  1302. DebugOption debugOptions[] =
  1303. {
  1304. DebugOption(options.peephole,"peephole", true),
  1305. DebugOption(options.foldConstantCast,"foldConstantCast", true),
  1306. DebugOption(options.optimizeBoolReturn,"optimizeBoolReturn", true),
  1307. DebugOption(options.checkRowOverflow,"checkRowOverflow", true),
  1308. DebugOption(options.freezePersists,"freezePersists", false),
  1309. DebugOption(options.maxRecordSize, "defaultMaxLengthRecord", MAX_RECORD_SIZE),
  1310. DebugOption(options.maxInlineDepth, "maxInlineDepth", 999), // a debugging setting...
  1311. DebugOption(options.checkRoxieRestrictions,"checkRoxieRestrictions", true), // a debug aid for running regression suite
  1312. DebugOption(options.checkThorRestrictions,"checkThorRestrictions", true), // a debug aid for running regression suite
  1313. DebugOption(options.allowCsvWorkunitRead,"allowStoredCsvFormat", false),
  1314. DebugOption(options.evaluateCoLocalRowInvariantInExtract,"evaluateCoLocalRowInvariantInExtract", false),
  1315. DebugOption(options.spanMultipleCpp,"spanMultipleCpp", false),
  1316. DebugOption(options.activitiesPerCpp, "<exception>", 0x7fffffff),
  1317. DebugOption(options.allowInlineSpill,"allowInlineSpill", true),
  1318. DebugOption(options.optimizeGlobalProjects,"optimizeGlobalProjects", false),
  1319. DebugOption(options.optimizeResourcedProjects,"optimizeResourcedProjects", false),
  1320. DebugOption(options.reduceNetworkTraffic,"aggressiveOptimizeProjects", false),
  1321. DebugOption(options.notifyOptimizedProjects, "notifyOptimizedProjects", 0),
  1322. DebugOption(options.optimizeProjectsPreservePersists,"optimizeProjectsPreservePersists", false),
  1323. DebugOption(options.checkAsserts,"checkAsserts", true),
  1324. DebugOption(options.optimizeLoopInvariant,"optimizeLoopInvariant", false), // doesn't fully work yet! and has little effect, and messes up the alias dependencies
  1325. DebugOption(options.defaultImplicitKeyedJoinLimit, "defaultImplicitKeyedJoinLimit", 10000),
  1326. DebugOption(options.defaultImplicitIndexReadLimit, "defaultImplicitIndexReadLimit", 0),
  1327. DebugOption(options.commonUpChildGraphs,"commonUpChildGraphs", true),
  1328. DebugOption(options.detectAmbiguousSelector,"detectAmbiguousSelector", false),
  1329. DebugOption(options.allowAmbiguousSelector,"allowAmbiguousSelector", false),
  1330. DebugOption(options.preserveUniqueSelector,"preserveUniqueSelector", true),
  1331. #ifdef _DEBUG
  1332. DebugOption(options.regressionTest,"regressionTest", true),
  1333. #else
  1334. DebugOption(options.regressionTest,"regressionTest", false),
  1335. #endif
  1336. DebugOption(options.addTimingToWorkunit, "addTimingToWorkunit", true),
  1337. //recreating case can cause duplicate branches in weird situations.
  1338. DebugOption(options.recreateMapFromIf,"recreateMapFromIf", !targetThor()),
  1339. DebugOption(options.showMetaText,"debugShowMetaText", false),
  1340. DebugOption(options.resourceSequential,"resourceSequential", false),
  1341. DebugOption(options.workunitTemporaries,"workunitTemporaries", true),
  1342. DebugOption(options.resourceConditionalActions,"resourceConditionalActions", false), //targetRoxie() ??
  1343. DebugOption(options.minimizeWorkunitTemporaries, "<exception>", false),
  1344. DebugOption(options.pickBestEngine,"pickBestEngine", true),
  1345. DebugOption(options.groupedChildIterators,"groupedChildIterators", false),
  1346. DebugOption(options.noAllToLookupConversion,"noAllToLookupConversion", false),
  1347. DebugOption(options.notifyWorkflowCse,"notifyWorkflowCse", true),
  1348. DebugOption(options.performWorkflowCse,"performWorkflowCse", false),
  1349. DebugOption(options.warnOnImplicitJoinLimit,"warnOnImplicitJoinLimit", targetRoxie()),
  1350. DebugOption(options.warnOnImplicitReadLimit,"warnOnImplicitReadLimit", targetRoxie()),
  1351. DebugOption(options.convertJoinToLookup,"convertJoinToLookup", true),
  1352. DebugOption(options.convertJoinToLookupIfSorted,"convertJoinToLookupIfSorted", false), // should change to false once tested
  1353. DebugOption(options.spotCSE,"spotCSE", true),
  1354. DebugOption(options.optimizeNonEmpty,"optimizeNonEmpty", !targetThor()), // not sure that it will be conditional resourced correctly for thor
  1355. DebugOption(options.allowVariableRoxieFilenames,"allowVariableRoxieFilenames", false),
  1356. DebugOption(options.foldConstantDatasets,"foldConstantDatasets", true),
  1357. DebugOption(options.hoistSimpleGlobal,"hoistSimpleGlobal", true),
  1358. DebugOption(options.percolateConstants,"percolateConstants", true),
  1359. DebugOption(options.percolateFilters,"percolateFilters", false),
  1360. DebugOption(options.usePrefetchForAllProjects,"usePrefetchForAllProjects", false),
  1361. DebugOption(options.allFilenamesDynamic,"allFilenamesDynamic", false),
  1362. DebugOption(options.optimizeSteppingPostfilter,"optimizeSteppingPostfilter", true),
  1363. DebugOption(options.moveUnconditionalActions,"moveUnconditionalActions", false),
  1364. DebugOption(options.paranoidCheckNormalized, "paranoidCheckNormalized", paranoid),
  1365. DebugOption(options.paranoidCheckDependencies, "paranoidCheckDependencies", paranoid),
  1366. DebugOption(options.preventKeyedSplit,"preventKeyedSplit", true),
  1367. DebugOption(options.preventSteppedSplit,"preventSteppedSplit", true),
  1368. DebugOption(options.canGenerateSimpleAction,"canGenerateSimpleAction", true),
  1369. DebugOption(options.minimizeActivityClasses,"minimizeActivityClasses", true),
  1370. DebugOption(options.maxRootMaybeThorActions, "maxRootMaybeThorActions", 0),
  1371. DebugOption(options.includeHelperInGraph,"includeHelperInGraph", false),
  1372. DebugOption(options.supportsLinkedChildRows,"supportsLinkedChildRows", (targetClusterType != ThorCluster)),
  1373. DebugOption(options.minimizeSkewBeforeSpill,"minimizeSkewBeforeSpill", false),
  1374. DebugOption(options.createSerializeForUnknownSize,"createSerializeForUnknownSize", false),
  1375. DebugOption(options.implicitLinkedChildRows,"implicitLinkedChildRows", false),
  1376. DebugOption(options.tempDatasetsUseLinkedRows,"tempDatasetsUseLinkedRows", false),
  1377. // DebugOption(options.mainRowsAreLinkCounted,"mainRowsAreLinkCounted", options.supportsLinkedChildRows),
  1378. DebugOption(options.allowSections,"allowSections", true),
  1379. DebugOption(options.autoPackRecords,"autoPackRecords", false),
  1380. DebugOption(options.commonUniqueNameAttributes,"commonUniqueNameAttributes", true),
  1381. DebugOption(options.sortIndexPayload,"sortIndexPayload", true),
  1382. DebugOption(options.foldFilter,"foldFilter", true),
  1383. DebugOption(options.finalizeAllRows, "finalizeAllRows", false),
  1384. DebugOption(options.finalizeAllVariableRows, "finalizeAllVariableRows", true),
  1385. DebugOption(options.maxStaticRowSize , "maxStaticRowSize", MAX_STATIC_ROW_SIZE),
  1386. DebugOption(options.maxLocalRowSize , "maxLocalRowSize", MAX_LOCAL_ROW_SIZE),
  1387. DebugOption(options.optimizeGraph,"optimizeGraph", true),
  1388. DebugOption(options.optimizeChildGraph,"optimizeChildGraph", false),
  1389. DebugOption(options.orderDiskFunnel,"orderDiskFunnel", true),
  1390. DebugOption(options.alwaysAllowAllNodes,"alwaysAllowAllNodes", false),
  1391. DebugOption(options.slidingJoins,"slidingJoins", false),
  1392. DebugOption(options.foldOptimized,"foldOptimized", false),
  1393. DebugOption(options.globalFold,"globalFold", true),
  1394. DebugOption(options.globalOptimize,"globalOptimize", false),
  1395. DebugOption(options.applyInstantEclTransformations,"applyInstantEclTransformations", false), // testing option
  1396. DebugOption(options.calculateComplexity,"calculateComplexity", false),
  1397. DebugOption(options.generateLogicalGraph,"generateLogicalGraph", false),
  1398. DebugOption(options.generateLogicalGraphOnly,"generateLogicalGraphOnly", false),
  1399. DebugOption(options.globalAutoHoist,"globalAutoHoist", true),
  1400. DebugOption(options.useLinkedRawIterator,"useLinkedRawIterator", false),
  1401. DebugOption(options.useLinkedNormalize,"useLinkedNormalize", false),
  1402. DebugOption(options.applyInstantEclTransformationsLimit, "applyInstantEclTransformationsLimit", 100),
  1403. DebugOption(options.insertProjectCostLevel, "insertProjectCostLevel", (unsigned)-1),
  1404. DebugOption(options.dfaRepeatMax, "dfaRepeatMax", 10),
  1405. DebugOption(options.dfaRepeatMaxScore, "dfaRepeatMaxScore", 100),
  1406. DebugOption(options.debugNlp, "debugNlp", DEFAULT_NLP_DETAIL),
  1407. DebugOption(options.regexVersion, "regexVersion",0),
  1408. DebugOption(options.parseDfaComplexity, "parseDfaComplexity", (unsigned)-1),
  1409. DebugOption(options.expandRepeatAnyAsDfa,"expandRepeatAnyAsDfa", true),
  1410. DebugOption(options.resourceMaxMemory, "resourceMaxMemory", 0),
  1411. DebugOption(options.resourceMaxSockets, "resourceMaxSockets", 0),
  1412. DebugOption(options.resourceMaxActivities, "resourceMaxActivities", 0),
  1413. DebugOption(options.resourceMaxHeavy, "resourceMaxHeavy", 1),
  1414. DebugOption(options.resourceMaxDistribute, "resourceMaxDistribute", 2),
  1415. DebugOption(options.unlimitedResources,"unlimitedResources", false),
  1416. DebugOption(options.resourceUseMpForDistribute,"resourceUseMpForDistribute", false),
  1417. DebugOption(options.filteredReadSpillThreshold, "filteredReadSpillThreshold", 999),
  1418. DebugOption(options.allowThroughSpill,"allowThroughSpill", true),
  1419. DebugOption(options.minimiseSpills,"minimiseSpills", false),
  1420. DebugOption(options.spillMultiCondition,"spillMultiCondition", false),
  1421. DebugOption(options.spotThroughAggregate,"spotThroughAggregate", true),
  1422. DebugOption(options.hoistResourced,"hoistResourced", true),
  1423. DebugOption(options.minimizeSpillSize, "minimizeSpillSize", 0),
  1424. DebugOption(options.maximizeLexer,"maximizeLexer", false),
  1425. DebugOption(options.foldStored,"foldStored", false),
  1426. DebugOption(options.spotTopN,"spotTopN", true),
  1427. DebugOption(options.topnLimit, "topnLimit", 10000),
  1428. DebugOption(options.groupAllDistribute,"groupAllDistribute", false),
  1429. DebugOption(options.spotLocalMerge,"spotLocalMerge", true),
  1430. DebugOption(options.spotPotentialKeyedJoins,"spotPotentialKeyedJoins", false),
  1431. DebugOption(options.combineTrivialStored,"combineTrivialStored", true),
  1432. DebugOption(options.combineAllStored,"combineAllStored", false),
  1433. DebugOption(options.allowStoredDuplicate,"allowStoredDuplicate", false), // only here as a temporary workaround
  1434. DebugOption(options.specifiedClusterSize, "clusterSize", 0),
  1435. DebugOption(options.globalFoldOptions, "globalFoldOptions", (unsigned)-1),
  1436. DebugOption(options.allowScopeMigrate,"allowScopeMigrate", true),
  1437. DebugOption(options.supportFilterProject,"supportFilterProject", true),
  1438. DebugOption(options.normalizeExplicitCasts,"normalizeExplicitCasts", true),
  1439. DebugOption(options.optimizeInlineSource,"optimizeInlineSource", false),
  1440. DebugOption(options.optimizeDiskSource,"optimizeDiskSource", true),
  1441. DebugOption(options.optimizeIndexSource,"optimizeIndexSource", true),
  1442. DebugOption(options.optimizeChildSource,"optimizeChildSource", false),
  1443. DebugOption(options.reportLocations,"reportLocations", true),
  1444. DebugOption(options.debugGeneratedCpp,"debugGeneratedCpp", false),
  1445. DebugOption(options.addFilesnamesToGraph,"addFilesnamesToGraph", true),
  1446. DebugOption(options.normalizeLocations,"normalizeLocations", true),
  1447. DebugOption(options.ensureRecordsHaveSymbols,"ensureRecordsHaveSymbols", true),
  1448. DebugOption(options.constantFoldNormalize,"constantFoldNormalize", true),
  1449. DebugOption(options.constantFoldPostNormalize,"constantFoldPostNormalize", false),
  1450. DebugOption(options.optimizeGrouping,"optimizeGrouping", true),
  1451. DebugOption(options.showMetaInGraph,"showMetaInGraph", false),
  1452. DebugOption(options.spotComplexClasses,"spotComplexClasses", true),
  1453. DebugOption(options.complexClassesThreshold,"complexClassesThreshold", 5000),
  1454. DebugOption(options.complexClassesActivityFilter,"complexClassesActivityFilter", 0),
  1455. DebugOption(options.optimizeString1Compare,"optimizeString1Compare", true),
  1456. DebugOption(options.optimizeSpillProject,"optimizeSpillProject", true),
  1457. DebugOption(options.expressionPeephole,"expressionPeephole", false),
  1458. DebugOption(options.optimizeIncrement,"optimizeIncrement", true),
  1459. DebugOption(options.supportsMergeDistribute,"supportsMergeDistribute", true),
  1460. DebugOption(options.debugNlpAsHint,"debugNlpAsHint", false),
  1461. DebugOption(options.forceVariableWuid,"forceVariableWuid", false),
  1462. DebugOption(options.okToDeclareAndAssign,"okToDeclareAndAssign", false),
  1463. DebugOption(options.noteRecordSizeInGraph,"noteRecordSizeInGraph", true),
  1464. DebugOption(options.convertRealAssignToMemcpy,"convertRealAssignToMemcpy", false),
  1465. DebugOption(options.allowActivityForKeyedJoin,"allowActivityForKeyedJoin", false),
  1466. DebugOption(options.forceActivityForKeyedJoin,"forceActivityForKeyedJoin", false),
  1467. DebugOption(options.addLibraryInputsToGraph,"addLibraryInputsToGraph", false),
  1468. DebugOption(options.showRecordCountInGraph,"showRecordCountInGraph", true),
  1469. DebugOption(options.serializeRowsetInExtract,"serializeRowsetInExtract", false),
  1470. DebugOption(options.optimizeInSegmentMonitor,"optimizeInSegmentMonitor", true),
  1471. DebugOption(options.supportDynamicRows,"supportDynamicRows", true),
  1472. DebugOption(options.testIgnoreMaxLength,"testIgnoreMaxLength", false),
  1473. DebugOption(options.limitMaxLength,"limitMaxLength", false),
  1474. DebugOption(options.trackDuplicateActivities,"trackDuplicateActivities", false),
  1475. DebugOption(options.showActivitySizeInGraph,"showActivitySizeInGraph", false),
  1476. DebugOption(options.addLocationToCpp,"addLocationToCpp", false),
  1477. DebugOption(options.alwaysCreateRowBuilder,"alwaysCreateRowBuilder", false),
  1478. DebugOption(options.precalculateFieldOffsets,"precalculateFieldOffsets", false),
  1479. DebugOption(options.generateStaticInlineTables,"generateStaticInlineTables", true),
  1480. DebugOption(options.staticRowsUseStringInitializer,"staticRowsUseStringInitializer", true),
  1481. DebugOption(options.convertWhenExecutedToCompound,"convertWhenExecutedToCompound", queryLegacyEclSemantics()),
  1482. DebugOption(options.standAloneExe,"standAloneExe", false),
  1483. DebugOption(options.enableCompoundCsvRead,"enableCompoundCsvRead", true),
  1484. // The following works 99% of the time, but disabled due to potential problems with the ambiguity of LEFT
  1485. //possibly causing filters on nested records to be incorrectly removed.
  1486. DebugOption(options.optimizeNestedConditional,"optimizeNestedConditional", false),
  1487. DebugOption(options.createImplicitAliases,"createImplicitAliases", false),
  1488. DebugOption(options.combineSiblingGraphs,"combineSiblingGraphs", true),
  1489. DebugOption(options.optimizeSharedGraphInputs,"optimizeSharedGraphInputs", true),
  1490. DebugOption(options.supportsShuffleActivity,"supportsShuffleActivity",false),
  1491. DebugOption(options.implicitShuffle,"implicitShuffle",false),
  1492. DebugOption(options.implicitBuildIndexShuffle,"implicitBuildIndexShuffle",false),
  1493. DebugOption(options.implicitJoinShuffle,"implicitJoinShuffle",false),
  1494. DebugOption(options.implicitGroupShuffle,"implicitGroupShuffle",false),
  1495. DebugOption(options.implicitGroupHashAggregate,"implicitGroupHashAggregate",false),
  1496. DebugOption(options.implicitGroupHashDedup,"implicitGroupHashDedup",false),
  1497. DebugOption(options.reportFieldUsage,"reportFieldUsage",false),
  1498. DebugOption(options.shuffleLocalJoinConditions,"shuffleLocalJoinConditions",false),
  1499. };
  1500. //get options values from workunit
  1501. const unsigned numDebugOptions = _elements_in(debugOptions);
  1502. Owned<IStringIterator> debugs(&wu()->getDebugValues());
  1503. SCMStringBuffer name, val;
  1504. ForEach(*debugs)
  1505. {
  1506. debugs->str(name);
  1507. wu()->getDebugValue(name.str(),val);
  1508. unsigned x = 0;
  1509. for (; x < numDebugOptions; x++)
  1510. {
  1511. if (0 == stricmp(name.str(), debugOptions[x].optName))
  1512. {
  1513. debugOptions[x].setValue(val.str());
  1514. break;
  1515. }
  1516. }
  1517. }
  1518. //The following cases handle options whose default values are dependent on other options.
  1519. //Or where one debug options sets more than one option
  1520. options.hasResourceUseMpForDistribute = wu()->hasDebugValue("resourceUseMpForDistribute");
  1521. if (!options.supportsLinkedChildRows)
  1522. options.implicitLinkedChildRows = false;
  1523. if (options.spanMultipleCpp)
  1524. {
  1525. options.activitiesPerCpp = wu()->getDebugValueInt("activitiesPerCpp", DEFAULT_ACTIVITIES_PER_CPP);
  1526. curCppFile = 1;
  1527. }
  1528. options.targetCompiler = DEFAULT_COMPILER;
  1529. if (wu()->hasDebugValue("targetGcc"))
  1530. options.targetCompiler = wu()->getDebugValueBool("targetGcc", false) ? GccCppCompiler : Vs6CppCompiler;
  1531. SCMStringBuffer compilerText;
  1532. wu()->getDebugValue("targetCompiler", compilerText);
  1533. for (CompilerType iComp = (CompilerType)0; iComp < MaxCompiler; iComp = (CompilerType)(iComp+1))
  1534. {
  1535. if (stricmp(compilerText.s.str(), compilerTypeText[iComp]) == 0)
  1536. options.targetCompiler = iComp;
  1537. }
  1538. if (getDebugFlag("optimizeProjects", true))
  1539. {
  1540. options.optimizeGlobalProjects = true;
  1541. options.optimizeResourcedProjects = true;
  1542. }
  1543. options.mainRowsAreLinkCounted = options.supportsLinkedChildRows && getDebugFlag("mainRowsAreLinkCounted", true);
  1544. options.minimizeWorkunitTemporaries = !options.workunitTemporaries || getDebugFlag("minimizeWorkunitTemporaries", false);//options.resourceConditionalActions);
  1545. options.tempDatasetsUseLinkedRows = getDebugFlag("tempDatasetsUseLinkedRows", options.implicitLinkedChildRows);
  1546. options.inlineStringThreshold = wu()->getDebugValueInt("inlineStringThreshold", (options.targetCompiler != Vs6CppCompiler) ? 0 : 10000);
  1547. if (!options.globalFold)
  1548. {
  1549. options.constantFoldNormalize = false;
  1550. options.constantFoldPostNormalize = false;
  1551. }
  1552. //A meta flag for enabling link counted child rows.
  1553. bool useLCR = getDebugFlag("linkCountedRows", getDebugFlag("testLCR", true));
  1554. if (options.supportsLinkedChildRows && useLCR)
  1555. {
  1556. options.implicitLinkedChildRows = true;
  1557. options.tempDatasetsUseLinkedRows = true;
  1558. options.useLinkedRawIterator = true;
  1559. options.useLinkedNormalize = true;
  1560. options.finalizeAllRows = true; // inline temporary rows should actually be ok.
  1561. options.finalizeAllVariableRows = true;
  1562. }
  1563. postProcessOptions();
  1564. }
  1565. void HqlCppTranslator::postProcessOptions()
  1566. {
  1567. //Any post processing - e.g., dependent flags goes here...
  1568. if (targetClusterType == ThorCluster)
  1569. {
  1570. options.supportDynamicRows = false;
  1571. options.resourceConditionalActions = false;
  1572. options.resourceSequential = false;
  1573. }
  1574. if (options.supportDynamicRows)
  1575. {
  1576. options.finalizeAllVariableRows = true;
  1577. }
  1578. else
  1579. {
  1580. options.testIgnoreMaxLength = false;
  1581. options.limitMaxLength = false;
  1582. }
  1583. if (options.supportsLinkedChildRows)
  1584. {
  1585. options.maxStaticRowSize = 0;
  1586. }
  1587. else
  1588. {
  1589. options.maxStaticRowSize = (unsigned)-1;
  1590. options.implicitLinkedChildRows = false;
  1591. options.tempDatasetsUseLinkedRows = false;
  1592. options.useLinkedRawIterator = false;
  1593. options.useLinkedNormalize = false;
  1594. options.finalizeAllRows = false;
  1595. options.finalizeAllVariableRows = false;
  1596. }
  1597. options.optimizeDiskFlag = 0;
  1598. if (options.optimizeInlineSource)
  1599. options.optimizeDiskFlag |= CSFnewinline;
  1600. if (options.optimizeDiskSource)
  1601. options.optimizeDiskFlag |= CSFnewdisk;
  1602. if (options.optimizeIndexSource)
  1603. options.optimizeDiskFlag |= CSFnewindex;
  1604. if (options.optimizeChildSource)
  1605. options.optimizeDiskFlag |= CSFnewchild;
  1606. if (!targetThor())
  1607. {
  1608. //Roxie doesn't gain from additional projects, hthor doesn't support split
  1609. options.optimizeSpillProject = false;
  1610. }
  1611. if (options.resourceSequential)
  1612. options.resourceConditionalActions = true;
  1613. //Probably best to ignore this warning. - possibly configure it based on some other option
  1614. queryWarningProcessor().addGlobalOnWarning(HQLWRN_FoldRemoveKeyed, ignoreAtom);
  1615. if (options.forceVariableWuid)
  1616. wu()->setCloneable(true);
  1617. }
  1618. unsigned HqlCppTranslator::getOptimizeFlags() const
  1619. {
  1620. unsigned optFlags = HOOfold;
  1621. switch (targetClusterType)
  1622. {
  1623. case RoxieCluster:
  1624. optFlags |= HOOnoclonelimit|HOOalwayslocal;
  1625. break;
  1626. case HThorCluster:
  1627. optFlags |= HOOnocloneindexlimit|HOOalwayslocal;
  1628. break;
  1629. case ThorCluster:
  1630. case ThorLCRCluster:
  1631. break;
  1632. default:
  1633. UNIMPLEMENTED;
  1634. }
  1635. if ((options.optimizeDiskFlag & CSFnewdisk) && (options.optimizeDiskFlag & CSFnewindex))
  1636. optFlags |= HOOhascompoundaggregate;
  1637. if (options.foldConstantDatasets)
  1638. optFlags |= HOOfoldconstantdatasets;
  1639. return optFlags;
  1640. }
  1641. void HqlCppTranslator::overrideOptionsForLibrary()
  1642. {
  1643. options.workunitTemporaries = false;
  1644. options.pickBestEngine = false;
  1645. options.minimizeWorkunitTemporaries = true;
  1646. }
  1647. void HqlCppTranslator::overrideOptionsForQuery()
  1648. {
  1649. options.workunitTemporaries = getDebugFlag("workunitTemporaries", true);
  1650. options.pickBestEngine = getDebugFlag("pickBestEngine", true);
  1651. options.minimizeWorkunitTemporaries = !options.workunitTemporaries || getDebugFlag("minimizeWorkunitTemporaries", false);//options.resourceConditionalActions);
  1652. }
  1653. IHqlExpression *HqlCppTranslator::addBigLiteral(const char *lit, unsigned litLen)
  1654. {
  1655. unsigned resid = code->addStringResource(litLen, lit);
  1656. HqlExprArray args;
  1657. args.append(*getSizetConstant(resid));
  1658. return bindTranslatedFunctionCall(loadResourceAtom, args);
  1659. }
  1660. IHqlExpression * HqlCppTranslator::addLiteral(const char * text)
  1661. {
  1662. return createConstant(text);
  1663. }
  1664. IHqlExpression *HqlCppTranslator::addDataLiteral(const char *lit, unsigned litLen)
  1665. {
  1666. if (!canGenerateStringInline(litLen))
  1667. return addBigLiteral(lit, litLen);
  1668. else
  1669. return createConstant(createStringValue(lit, litLen));
  1670. }
  1671. IHqlExpression *HqlCppTranslator::addStringLiteral(const char *lit)
  1672. {
  1673. unsigned litLen = strlen(lit);
  1674. if (!canGenerateStringInline(litLen))
  1675. return addBigLiteral(lit, litLen+1);
  1676. else
  1677. return createConstant(createStringValue(lit, litLen));
  1678. }
  1679. bool HqlCppTranslator::allowEmbeddedCpp()
  1680. {
  1681. if (!checkedEmbeddedCpp)
  1682. {
  1683. cachedAllowEmbeddedCpp = ctxCallback->allowAccess("cpp");
  1684. checkedEmbeddedCpp = true;
  1685. }
  1686. return cachedAllowEmbeddedCpp;
  1687. }
  1688. void HqlCppTranslator::checkPipeAllowed()
  1689. {
  1690. if (!checkedPipeAllowed)
  1691. {
  1692. if (!ctxCallback->allowAccess("pipe"))
  1693. throwError(HQLERR_PipeNotAllowed);
  1694. checkedPipeAllowed = true;
  1695. }
  1696. }
  1697. IHqlExpression * HqlCppTranslator::bindFunctionCall(_ATOM name, HqlExprArray & args)
  1698. {
  1699. OwnedHqlExpr function = needFunction(name);
  1700. assertex(function != NULL);
  1701. return bindFunctionCall(function, args);
  1702. }
  1703. IHqlExpression * HqlCppTranslator::bindFunctionCall(_ATOM name, IHqlExpression * arg1)
  1704. {
  1705. HqlExprArray args;
  1706. args.append(*arg1);
  1707. return bindFunctionCall(name, args);
  1708. }
  1709. IHqlExpression * HqlCppTranslator::bindFunctionCall(IHqlExpression * function, HqlExprArray & args)
  1710. {
  1711. useFunction(function);
  1712. IHqlExpression * ret = createBoundFunction(NULL, function, args, NULL, false);
  1713. assertex(ret->queryExternalDefinition());
  1714. args.kill();
  1715. return ret;
  1716. }
  1717. IHqlExpression * HqlCppTranslator::bindFunctionCall(_ATOM name, HqlExprArray & args, ITypeInfo * newType)
  1718. {
  1719. if (!newType)
  1720. return bindFunctionCall(name, args);
  1721. OwnedHqlExpr function = needFunction(name);
  1722. useFunction(function);
  1723. assertex(function->getOperator() == no_funcdef);
  1724. IHqlExpression * body = function->queryChild(0);
  1725. HqlExprArray bodyArgs;
  1726. unwindChildren(bodyArgs, body);
  1727. HqlExprArray funcArgs;
  1728. funcArgs.append(*createValue(body->getOperator(), LINK(newType), bodyArgs));
  1729. unwindChildren(funcArgs, function, 1);
  1730. ITypeInfo * funcType = makeFunctionType(LINK(newType), LINK(function->queryChild(1)), LINK(function->queryChild(2)));
  1731. OwnedHqlExpr newFunction = createValue(function->getOperator(), funcType, funcArgs);
  1732. return bindFunctionCall(newFunction, args);
  1733. }
  1734. IHqlExpression * HqlCppTranslator::bindTranslatedFunctionCall(IHqlExpression * function, HqlExprArray & args)
  1735. {
  1736. useFunction(function);
  1737. IHqlExpression * ret = createTranslatedExternalCall(NULL, function, args);
  1738. assertex(ret->queryExternalDefinition());
  1739. args.kill();
  1740. return ret;
  1741. }
  1742. IHqlExpression * HqlCppTranslator::bindTranslatedFunctionCall(_ATOM name, HqlExprArray & args)
  1743. {
  1744. OwnedHqlExpr function = needFunction(name);
  1745. return bindTranslatedFunctionCall(function, args);
  1746. }
  1747. void HqlCppTranslator::buildTranslatedFunctionCall(BuildCtx & ctx, _ATOM name, HqlExprArray & args)
  1748. {
  1749. OwnedHqlExpr call = bindTranslatedFunctionCall(name, args);
  1750. ctx.addExpr(call);
  1751. }
  1752. void HqlCppTranslator::buildFunctionCall(BuildCtx & ctx, _ATOM name, HqlExprArray & args)
  1753. {
  1754. OwnedHqlExpr call = bindFunctionCall(name, args);
  1755. buildStmt(ctx, call);
  1756. }
  1757. /* Args: all elements in it are LINKED */
  1758. void HqlCppTranslator::callProcedure(BuildCtx & ctx, _ATOM name, HqlExprArray & args)
  1759. {
  1760. OwnedHqlExpr call = bindTranslatedFunctionCall(name, args);
  1761. assertex(call->queryExternalDefinition());
  1762. ctx.addExpr(call);
  1763. }
  1764. bool HqlCppTranslator::getDebugFlag(const char * name, bool defValue)
  1765. {
  1766. return wu()->getDebugValueBool(name, defValue);
  1767. }
  1768. void HqlCppTranslator::doReportWarning(IHqlExpression * location, unsigned id, const char * msg)
  1769. {
  1770. Owned<IECLError> warnError;
  1771. if (!location)
  1772. location = queryActiveActivityLocation();
  1773. if (location)
  1774. warnError.setown(createECLError(false, id, msg, location->querySourcePath()->str(), location->getStartLine(), location->getStartColumn(), 0));
  1775. else
  1776. warnError.setown(createECLError(false, id, msg, NULL, 0, 0, 0));
  1777. warningProcessor.report(NULL, errors, warnError);
  1778. }
  1779. void HqlCppTranslator::reportWarning(IHqlExpression * location, unsigned id, const char * msg, ...)
  1780. {
  1781. StringBuffer s;
  1782. va_list args;
  1783. va_start(args, msg);
  1784. s.valist_appendf(msg, args);
  1785. va_end(args);
  1786. doReportWarning(location, id, s.str());
  1787. }
  1788. void HqlCppTranslator::reportWarning(unsigned id, const char * msg, ...)
  1789. {
  1790. StringBuffer s;
  1791. va_list args;
  1792. va_start(args, msg);
  1793. s.valist_appendf(msg, args);
  1794. va_end(args);
  1795. doReportWarning(NULL, id, s.str());
  1796. }
  1797. void HqlCppTranslator::addWorkunitException(WUExceptionSeverity severity, unsigned code, const char * text, IHqlExpression * location)
  1798. {
  1799. Owned<IWUException> msg = wu()->createException();
  1800. msg->setExceptionSource("Code Generator");
  1801. if (code)
  1802. msg->setExceptionCode(code);
  1803. msg->setExceptionMessage(text);
  1804. msg->setSeverity(severity);
  1805. msg->setTimeStamp(NULL);
  1806. if (!location)
  1807. location = queryActiveActivityLocation();
  1808. if (location)
  1809. {
  1810. msg->setExceptionFileName(location->querySourcePath()->str());
  1811. msg->setExceptionLineNo(location->getStartLine());
  1812. msg->setExceptionColumn(location->getStartColumn());
  1813. }
  1814. }
  1815. IHqlExpression * HqlCppTranslator::queryActiveNamedActivity()
  1816. {
  1817. ForEachItemInRev(i, activityExprStack)
  1818. {
  1819. IHqlExpression & cur = activityExprStack.item(i);
  1820. IHqlExpression * symbol = queryNamedSymbol(&cur);
  1821. if (symbol && symbol->querySourcePath())
  1822. return symbol;
  1823. if (isCompoundSource(&cur))
  1824. {
  1825. IHqlExpression * child = cur.queryChild(0);
  1826. if (hasNamedSymbol(child))
  1827. return child;
  1828. }
  1829. }
  1830. return NULL;
  1831. }
  1832. IHqlExpression * HqlCppTranslator::queryActiveActivityLocation() const
  1833. {
  1834. ForEachItemInRev(i, activityExprStack)
  1835. {
  1836. IHqlExpression & cur = activityExprStack.item(i);
  1837. IHqlExpression * location = queryLocation(&cur);
  1838. if (location)
  1839. return location;
  1840. if (isCompoundSource(&cur))
  1841. {
  1842. location = queryLocation(cur.queryChild(0));
  1843. if (location)
  1844. return location;
  1845. }
  1846. }
  1847. return NULL;
  1848. }
  1849. void HqlCppTranslator::ThrowStringException(int code,const char *format, ...)
  1850. {
  1851. IHqlExpression * location = queryActiveActivityLocation();
  1852. if (errors && location)
  1853. {
  1854. StringBuffer errorMsg;
  1855. va_list args;
  1856. va_start(args, format);
  1857. errorMsg.valist_appendf(format, args);
  1858. va_end(args);
  1859. throw createECLError(code, errorMsg.str(), location->querySourcePath()->str(), location->getStartLine(), location->getStartColumn(), 0);
  1860. }
  1861. va_list args;
  1862. va_start(args, format);
  1863. IException *ret = MakeStringExceptionVA(code, format, args);
  1864. va_end(args);
  1865. throw ret;
  1866. }
  1867. void HqlCppTranslator::reportErrorDirect(IHqlExpression * location, int code,const char *msg, bool alwaysAbort)
  1868. {
  1869. if (location)
  1870. {
  1871. ECLlocation loc;
  1872. loc.extractLocationAttr(location);
  1873. if (alwaysAbort)
  1874. throw createECLError(code, msg, loc.sourcePath->str(), loc.lineno, loc.column, loc.position);
  1875. errors->reportError(code, msg, loc.sourcePath->str(), loc.lineno, loc.column, loc.position);
  1876. }
  1877. else
  1878. throw MakeStringExceptionDirect(code, msg);
  1879. }
  1880. void HqlCppTranslator::reportError(IHqlExpression * location, int code,const char *format, ...)
  1881. {
  1882. StringBuffer errorMsg;
  1883. va_list args;
  1884. va_start(args, format);
  1885. errorMsg.valist_appendf(format, args);
  1886. va_end(args);
  1887. reportErrorDirect(location, code, errorMsg.str(), true);
  1888. }
  1889. //---------------------------------------------------------------------------
  1890. void HqlCppTranslator::doBuildStmtAssign(BuildCtx & ctx, IHqlExpression * target, IHqlExpression * expr)
  1891. {
  1892. buildAssign(ctx, target, expr);
  1893. }
  1894. void HqlCppTranslator::buildAddress(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  1895. {
  1896. node_operator op = expr->getOperator();
  1897. switch (op)
  1898. {
  1899. case no_address:
  1900. buildExpr(ctx, expr->queryChild(0), tgt);
  1901. break;
  1902. case no_typetransfer:
  1903. buildAddress(ctx, expr->queryChild(0), tgt);
  1904. break;
  1905. default:
  1906. {
  1907. Owned<IReferenceSelector> selector = buildReference(ctx, expr);
  1908. selector->buildAddress(ctx, tgt);
  1909. break;
  1910. }
  1911. }
  1912. }
  1913. bool HqlCppTranslator::hasAddress(BuildCtx & ctx, IHqlExpression * expr)
  1914. {
  1915. switch (expr->getOperator())
  1916. {
  1917. case no_deref:
  1918. case no_variable:
  1919. return true;
  1920. case no_field:
  1921. case no_select:
  1922. {
  1923. Owned<IReferenceSelector> selector = buildReference(ctx, expr);
  1924. return !selector->isConditional();
  1925. }
  1926. case no_typetransfer:
  1927. return hasAddress(ctx, expr->queryChild(0));
  1928. default:
  1929. return false;
  1930. }
  1931. }
  1932. void HqlCppTranslator::buildAssign(BuildCtx & ctx, IHqlExpression * target, IHqlExpression * expr)
  1933. {
  1934. #ifdef ADD_ASSIGNMENT_COMMENTS
  1935. if (target->getOperator() == no_select)
  1936. {
  1937. StringBuffer s;
  1938. ctx.addQuoted(s.append("//Assign to field ").append(target->queryChild(1)->queryName()));
  1939. }
  1940. #endif
  1941. Owned<IReferenceSelector> selector = buildReference(ctx, target);
  1942. if (expr->getOperator() == no_null)
  1943. selector->buildClear(ctx, 0);
  1944. else if (target->isDatarow() && (!hasReferenceModifier(target->queryType()) || !recordTypesMatch(target->queryType(), expr->queryType())))
  1945. buildRowAssign(ctx, selector, expr);
  1946. else
  1947. selector->set(ctx, expr);
  1948. }
  1949. void HqlCppTranslator::doBuildStmtAssignModify(BuildCtx & ctx, IHqlExpression * target, IHqlExpression * expr, node_operator assignOp)
  1950. {
  1951. Owned<IReferenceSelector> selector = buildReference(ctx, target);
  1952. selector->modifyOp(ctx, expr, assignOp);
  1953. }
  1954. void HqlCppTranslator::buildExprAssign(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  1955. {
  1956. /*
  1957. switch (target.queryType().getTypeCode())
  1958. {
  1959. case type_table:
  1960. case type_groupedtable:
  1961. buildDatasetAssign(ctx, target, expr);
  1962. break;
  1963. case type_row:
  1964. buildAssignRow(ctx, target, expr);
  1965. break;
  1966. }
  1967. */
  1968. node_operator op = expr->getOperator();
  1969. switch (op)
  1970. {
  1971. case no_constant:
  1972. if (!isNullAssign(target, expr))
  1973. doBuildExprAssign(ctx, target, expr);
  1974. else
  1975. ctx.addAssign(target.length, queryZero());
  1976. break;
  1977. case no_regex_find:
  1978. case no_regex_replace:
  1979. doBuildAssignRegexFindReplace(ctx, target, expr);
  1980. break;
  1981. case no_matched:
  1982. case no_matchtext:
  1983. case no_matchlength:
  1984. case no_matchposition:
  1985. case no_matchunicode:
  1986. case no_matchutf8:
  1987. doBuildMatched(ctx, &target, expr, NULL);
  1988. break;
  1989. case no_matchattr:
  1990. doBuildMatchAttr(ctx, &target, expr, NULL);
  1991. break;
  1992. case no_loopcounter:
  1993. doBuildAssignLoopCounter(ctx, target, expr);
  1994. break;
  1995. case no_evalonce:
  1996. doBuildEvalOnce(ctx, &target, expr, NULL);
  1997. break;
  1998. case no_alias_scope:
  1999. {
  2000. expandAliasScope(ctx, expr);
  2001. buildExprAssign(ctx, target, expr->queryChild(0));
  2002. break;
  2003. }
  2004. case no_case:
  2005. case no_map:
  2006. {
  2007. HqlCppCaseInfo info(*this);
  2008. doBuildCaseInfo(expr, info);
  2009. info.buildAssign(ctx, target);
  2010. break;
  2011. }
  2012. case no_which:
  2013. case no_rejected:
  2014. doBuildAssignWhich(ctx, target, expr);
  2015. break;
  2016. case no_call:
  2017. case no_externalcall:
  2018. doBuildAssignCall(ctx, target, expr);
  2019. break;
  2020. case no_cast:
  2021. case no_implicitcast:
  2022. doBuildAssignCast(ctx, target, expr);
  2023. break;
  2024. case no_choose:
  2025. doBuildAssignChoose(ctx, target, expr);
  2026. break;
  2027. case no_comma:
  2028. case no_compound:
  2029. buildStmt(ctx, expr->queryChild(0));
  2030. buildExprAssign(ctx, target, expr->queryChild(1));
  2031. break;
  2032. case no_concat:
  2033. doBuildAssignConcat(ctx, target, expr);
  2034. break;
  2035. case no_div:
  2036. case no_modulus:
  2037. doBuildAssignDivide(ctx, target, expr);
  2038. break;
  2039. case no_crc:
  2040. case no_hash:
  2041. case no_hash32:
  2042. case no_hash64:
  2043. doBuildAssignHashCrc(ctx, target, expr);
  2044. break;
  2045. case no_hashmd5:
  2046. doBuildAssignHashMd5(ctx, target, expr);
  2047. break;
  2048. case no_if:
  2049. doBuildAssignIf(ctx, target, expr);
  2050. break;
  2051. case no_index:
  2052. doBuildAssignIndex(ctx, target, expr);
  2053. break;
  2054. case no_in:
  2055. case no_notin:
  2056. {
  2057. OwnedHqlExpr optimized = querySimplifyInExpr(expr);
  2058. if (options.globalFold && optimized)
  2059. {
  2060. OwnedHqlExpr folded = foldHqlExpression(optimized);
  2061. buildExprAssign(ctx, target, folded);
  2062. }
  2063. else
  2064. doBuildAssignIn(ctx, target, expr);
  2065. break;
  2066. }
  2067. case no_intformat:
  2068. doBuildAssignFormat(intFormatAtom, ctx, target, expr);
  2069. break;
  2070. case no_nofold:
  2071. case no_nohoist:
  2072. case no_section:
  2073. case no_sectioninput:
  2074. buildExprAssign(ctx, target, expr->queryChild(0));
  2075. break;
  2076. case no_realformat:
  2077. doBuildAssignFormat(realFormatAtom, ctx, target, expr);
  2078. break;
  2079. case no_order:
  2080. doBuildAssignOrder(ctx, target, expr);
  2081. break;
  2082. case no_unicodeorder:
  2083. doBuildAssignUnicodeOrder(ctx, target, expr);
  2084. break;
  2085. case no_substring:
  2086. doBuildAssignSubString(ctx, target, expr);
  2087. break;
  2088. case no_trim:
  2089. doBuildAssignTrim(ctx, target, expr);
  2090. break;
  2091. case no_field:
  2092. throwUnexpected();
  2093. case no_select:
  2094. {
  2095. OwnedHqlExpr aggregate = convertToSimpleAggregate(expr);
  2096. if (aggregate && canProcessInline(&ctx, aggregate->queryChild(0)))
  2097. {
  2098. buildExprAssign(ctx, target, aggregate);
  2099. return;
  2100. }
  2101. Owned<IReferenceSelector> selector = buildReference(ctx, expr);
  2102. selector->assignTo(ctx, target);
  2103. return;
  2104. }
  2105. break;
  2106. case no_not:
  2107. {
  2108. IHqlExpression * child = expr->queryChild(0);
  2109. node_operator childOp = child->getOperator();
  2110. if (((childOp == no_and) || (childOp == no_or)) && requiresTempAfterFirst(ctx, child))
  2111. {
  2112. if (childOp == no_and)
  2113. doBuildAssignAnd(ctx, target, child, true);
  2114. else
  2115. {
  2116. OwnedHqlExpr inverted = convertOrToAnd(expr);
  2117. buildExprAssign(ctx, target, inverted);
  2118. }
  2119. }
  2120. else
  2121. doBuildExprAssign(ctx, target, expr);
  2122. break;
  2123. }
  2124. case no_or:
  2125. {
  2126. IHqlExpression * left = expr->queryChild(0);
  2127. //in always goes via an assign, so do this first, and then filter on result.
  2128. if (left->getOperator() == no_in)
  2129. {
  2130. BuildCtx subctx(ctx);
  2131. buildExprAssign(subctx, target, left);
  2132. OwnedHqlExpr inverse = getInverse(target.expr);
  2133. subctx.addFilter(inverse);
  2134. buildExprAssign(subctx, target, expr->queryChild(1));
  2135. }
  2136. else if (requiresTempAfterFirst(ctx, expr))
  2137. {
  2138. OwnedHqlExpr inverted = convertOrToAnd(expr);
  2139. buildExprAssign(ctx, target, inverted);
  2140. }
  2141. else
  2142. doBuildExprAssign(ctx, target, expr);
  2143. break;
  2144. }
  2145. case no_and:
  2146. if (requiresTempAfterFirst(ctx, expr))
  2147. doBuildAssignAnd(ctx, target, expr, false);
  2148. else
  2149. doBuildExprAssign(ctx, target, expr);
  2150. break;
  2151. case no_fromunicode:
  2152. case no_tounicode:
  2153. doBuildAssignToFromUnicode(ctx, target, expr);
  2154. break;
  2155. case no_toxml:
  2156. doBuildAssignToXml(ctx, target, expr);
  2157. break;
  2158. case no_wuid:
  2159. doBuildAssignWuid(ctx, target, expr);
  2160. break;
  2161. case no_xmldecode:
  2162. case no_xmlencode:
  2163. doBuildXmlEncode(ctx, &target, expr, NULL);
  2164. break;
  2165. case no_all:
  2166. doBuildAssignAll(ctx, target, expr);
  2167. return;
  2168. case no_list:
  2169. doBuildAssignList(ctx, target, expr);
  2170. return;
  2171. case no_addsets:
  2172. doBuildAssignAddSets(ctx, target, expr);
  2173. return;
  2174. case no_createset:
  2175. buildSetAssignViaBuilder(ctx, target, expr);
  2176. return;
  2177. case no_failmessage:
  2178. doBuildAssignFailMessage(ctx, target, expr);
  2179. return;
  2180. case no_eventname:
  2181. doBuildAssignEventName(ctx, target, expr);
  2182. return;
  2183. case no_eventextra:
  2184. doBuildAssignEventExtra(ctx, target, expr);
  2185. return;
  2186. case no_catch:
  2187. doBuildAssignCatch(ctx, target, expr);
  2188. break;
  2189. case no_id2blob:
  2190. doBuildAssignIdToBlob(ctx, target, expr);
  2191. break;
  2192. case no_getresult:
  2193. case no_workunit_dataset:
  2194. if (isSameFullyUnqualifiedType(expr->queryType(), target.queryType()))
  2195. doBuildAssignGetResult(ctx, target, expr);
  2196. else
  2197. doBuildExprAssign(ctx, target, expr);
  2198. break;
  2199. case no_getgraphresult:
  2200. doBuildAssignGetGraphResult(ctx, target, expr);
  2201. break;
  2202. case no_existslist:
  2203. doBuildAggregateList(ctx, &target, expr, NULL);
  2204. break;
  2205. case no_countlist:
  2206. doBuildAggregateList(ctx, &target, expr, NULL);
  2207. break;
  2208. case no_sumlist:
  2209. doBuildAggregateList(ctx, &target, expr, NULL);
  2210. break;
  2211. case no_minlist:
  2212. doBuildAggregateList(ctx, &target, expr, NULL);
  2213. break;
  2214. case no_maxlist:
  2215. doBuildAggregateList(ctx, &target, expr, NULL);
  2216. break;
  2217. case no_skip:
  2218. {
  2219. bool canReachFollowing = false;
  2220. doBuildStmtSkip(ctx, expr, &canReachFollowing);
  2221. if (canReachFollowing)
  2222. {
  2223. OwnedHqlExpr null = createNullExpr(expr);
  2224. doBuildExprAssign(ctx, target, null);
  2225. }
  2226. break;
  2227. }
  2228. case no_count:
  2229. case no_max:
  2230. case no_min:
  2231. case no_sum:
  2232. case no_exists:
  2233. doBuildAssignAggregate(ctx, target, expr);
  2234. break;
  2235. case no_getenv:
  2236. {
  2237. OwnedHqlExpr mapped = cvtGetEnvToCall(expr);
  2238. buildExprAssign(ctx, target, mapped);
  2239. break;
  2240. }
  2241. default:
  2242. doBuildExprAssign(ctx, target, expr);
  2243. break;
  2244. }
  2245. }
  2246. void HqlCppTranslator::buildExprAssignViaType(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr, ITypeInfo * type)
  2247. {
  2248. OwnedHqlExpr temp = createValue(no_implicitcast, LINK(type), LINK(expr));
  2249. buildExprAssign(ctx, target, temp);
  2250. }
  2251. void HqlCppTranslator::buildExprAssignViaString(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr, unsigned len)
  2252. {
  2253. OwnedITypeInfo type = makeStringType(len, NULL, NULL);
  2254. buildExprAssignViaType(ctx, target, expr, type);
  2255. }
  2256. void HqlCppTranslator::buildAssignToTemp(BuildCtx & ctx, IHqlExpression * variable, IHqlExpression * expr)
  2257. {
  2258. CHqlBoundTarget boundTarget;
  2259. boundTarget.expr.set(variable);
  2260. buildExprAssign(ctx, boundTarget, expr);
  2261. }
  2262. void HqlCppTranslator::buildAssignViaTemp(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  2263. {
  2264. CHqlBoundExpr temp;
  2265. buildTempExpr(ctx, expr, temp);
  2266. buildExprAssign(ctx, target, temp.expr);
  2267. }
  2268. static bool canOptimizeIncrementAssign(ITypeInfo * type)
  2269. {
  2270. switch (type->getTypeCode())
  2271. {
  2272. case type_real:
  2273. return true;
  2274. case type_int:
  2275. switch (type->getSize())
  2276. {
  2277. case 1:
  2278. case 2:
  2279. case 4:
  2280. case 8:
  2281. return true;
  2282. }
  2283. }
  2284. return false;
  2285. }
  2286. IHqlExpression * HqlCppTranslator::optimizeIncrementAssign(BuildCtx & ctx, IHqlExpression * value)
  2287. {
  2288. //MORE: Could spot x += if(cond, y, 0) and convert to if (cond) x+= y; (especially if y is 1)
  2289. if (value->getOperator() == no_if)
  2290. {
  2291. IHqlExpression * left = value->queryChild(1);
  2292. IHqlExpression * right = value->queryChild(2);
  2293. if (isZero(right))
  2294. {
  2295. buildFilter(ctx, value->queryChild(0));
  2296. return optimizeIncrementAssign(ctx, left);
  2297. }
  2298. if (isZero(left))
  2299. {
  2300. OwnedHqlExpr filter = getInverse(value->queryChild(0));
  2301. buildFilter(ctx, filter);
  2302. return optimizeIncrementAssign(ctx, right);
  2303. }
  2304. }
  2305. if (isCast(value))
  2306. {
  2307. IHqlExpression * uncast = value->queryChild(0);
  2308. OwnedHqlExpr optimizedValue = optimizeIncrementAssign(ctx, uncast);
  2309. if (optimizedValue != uncast)
  2310. return ensureExprType(optimizedValue, value->queryType());
  2311. }
  2312. return LINK(value);
  2313. }
  2314. void HqlCppTranslator::buildIncrementAssign(BuildCtx & ctx, IHqlExpression * target, IHqlExpression * value)
  2315. {
  2316. // CHqlBoundExpr bound;
  2317. // buildExpr(ctx, target, bound);
  2318. ITypeInfo * type = target->queryType();
  2319. OwnedHqlExpr castValue = ensureExprType(value, type);
  2320. BuildCtx condctx(ctx);
  2321. if (options.optimizeIncrement)
  2322. {
  2323. castValue.setown(optimizeIncrementAssign(condctx, castValue));
  2324. if (isZero(castValue))
  2325. return;
  2326. if (canOptimizeIncrementAssign(type))
  2327. {
  2328. CHqlBoundExpr boundTarget;
  2329. buildExpr(condctx, target, boundTarget); // Not very clean!
  2330. CHqlBoundExpr boundValue;
  2331. buildExpr(condctx, castValue, boundValue);
  2332. condctx.addAssignIncrement(boundTarget.expr, boundValue.expr);
  2333. return;
  2334. }
  2335. }
  2336. OwnedHqlExpr plus = createValue(no_add, LINK(target), castValue.getClear());
  2337. buildAssign(condctx, target, plus);
  2338. }
  2339. void HqlCppTranslator::buildIncrementAssign(BuildCtx & ctx, IReferenceSelector * target, IHqlExpression * value)
  2340. {
  2341. buildIncrementAssign(ctx, target->queryExpr(), value);
  2342. // OwnedHqlExpr plus = createValue(no_add, LINK(type), ensureExprType(target->queryExpr(), type), ensureExprType(value, type));
  2343. // target->set(condctx, plus);
  2344. }
  2345. void HqlCppTranslator::buildIncrementAssign(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * value)
  2346. {
  2347. ITypeInfo * type = target.queryType();
  2348. OwnedHqlExpr castValue = ensureExprType(value, type);
  2349. BuildCtx condctx(ctx);
  2350. if (options.optimizeIncrement)
  2351. {
  2352. castValue.setown(optimizeIncrementAssign(condctx, castValue));
  2353. if (isZero(castValue))
  2354. return;
  2355. if (canOptimizeIncrementAssign(type))
  2356. {
  2357. CHqlBoundExpr boundValue;
  2358. buildExpr(ctx, castValue, boundValue);
  2359. ctx.addAssignIncrement(target.expr, boundValue.expr);
  2360. return;
  2361. }
  2362. }
  2363. OwnedHqlExpr plus = createValue(no_add, target.getTranslatedExpr(), castValue.getClear());
  2364. buildExprAssign(ctx, target, plus);
  2365. }
  2366. void HqlCppTranslator::buildClear(BuildCtx & ctx, IHqlExpression * expr)
  2367. {
  2368. OwnedHqlExpr null = createNullExpr(expr);
  2369. buildAssign(ctx, expr, null);
  2370. }
  2371. void HqlCppTranslator::buildClear(BuildCtx & ctx, const CHqlBoundTarget & target)
  2372. {
  2373. if (target.length)
  2374. {
  2375. buildAssignToTemp(ctx, target.length, queryZero());
  2376. //NB: Don't need to clear target.pointer/target.variable if a length is defined......
  2377. return;
  2378. }
  2379. if (target.isFixedSize())
  2380. {
  2381. OwnedHqlExpr null = createNullExpr(target.expr);
  2382. buildExprAssign(ctx, target, null);
  2383. }
  2384. else
  2385. {
  2386. StringBuffer code;
  2387. if (hasWrapperModifier(target.queryType()))
  2388. generateExprCpp(code, target.expr).append(".clear();");
  2389. else
  2390. generateExprCpp(code, target.expr).append(" = 0;");
  2391. ctx.addQuoted(code);
  2392. }
  2393. }
  2394. void HqlCppTranslator::buildFilter(BuildCtx & ctx, IHqlExpression * expr)
  2395. {
  2396. node_operator op = expr->getOperator();
  2397. switch (op)
  2398. {
  2399. case no_attr:
  2400. case no_attr_expr:
  2401. case no_attr_link:
  2402. return;
  2403. case no_and:
  2404. doBuildFilterAnd(ctx, expr);
  2405. return;
  2406. case no_not:
  2407. {
  2408. IHqlExpression * child = expr->queryChild(0);
  2409. if ((child->getOperator() == no_or) && requiresTempAfterFirst(ctx, child))
  2410. {
  2411. OwnedHqlExpr inverted = convertOrToAnd(expr);
  2412. buildFilter(ctx,inverted);
  2413. return;
  2414. }
  2415. }
  2416. break;
  2417. case no_or:
  2418. if (!(hints & HintSize) && requiresTempAfterFirst(ctx, expr))
  2419. {
  2420. OwnedHqlExpr inverted = convertOrToAnd(expr);
  2421. buildFilter(ctx, inverted);
  2422. return;
  2423. }
  2424. break;
  2425. case no_between:
  2426. case no_notbetween:
  2427. {
  2428. OwnedHqlExpr between = expandBetween(expr);
  2429. buildFilter(ctx, between);
  2430. return;
  2431. }
  2432. case no_alias_scope:
  2433. {
  2434. expandAliasScope(ctx, expr);
  2435. buildFilter(ctx, expr->queryChild(0));
  2436. return;
  2437. }
  2438. }
  2439. buildFilterViaExpr(ctx, expr);
  2440. }
  2441. IHqlStmt * HqlCppTranslator::buildFilterViaExpr(BuildCtx & ctx, IHqlExpression * expr)
  2442. {
  2443. //default action...
  2444. CHqlBoundExpr pure;
  2445. buildExpr(ctx, expr, pure);
  2446. if (pure.length) // check length is non zero
  2447. return ctx.addFilter(pure.length);
  2448. else
  2449. {
  2450. IHqlStmt * stmt = ctx.addFilter(pure.expr);
  2451. ctx.associateExpr(expr, queryBoolExpr(true));
  2452. return stmt;
  2453. }
  2454. }
  2455. void HqlCppTranslator::tidyupExpr(BuildCtx & ctx, CHqlBoundExpr & bound)
  2456. {
  2457. if (isPushed(bound))
  2458. {
  2459. HqlExprArray args;
  2460. callProcedure(ctx, DecPopLongAtom, args);
  2461. bound.expr.set(NULL);
  2462. }
  2463. }
  2464. void HqlCppTranslator::expandTranslated(IHqlExpression * expr, CHqlBoundExpr & tgt)
  2465. {
  2466. tgt.setFromTranslated(expr);
  2467. }
  2468. void HqlCppTranslator::buildCachedExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  2469. {
  2470. buildExpr(ctx, expr, tgt);
  2471. }
  2472. void HqlCppTranslator::buildAnyExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  2473. {
  2474. if (expr->isDataset())
  2475. buildDataset(ctx, expr, tgt, FormatNatural);
  2476. else if (expr->isDatarow())
  2477. {
  2478. Owned<IReferenceSelector> selector = buildNewRow(ctx, expr);
  2479. selector->buildAddress(ctx, tgt);
  2480. }
  2481. else
  2482. buildExpr(ctx, expr, tgt);
  2483. }
  2484. void HqlCppTranslator::buildExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  2485. {
  2486. node_operator op = expr->getOperator();
  2487. switch (op)
  2488. {
  2489. case no_counter:
  2490. doBuildExprCounter(ctx, expr, tgt);
  2491. return;
  2492. case no_evaluate:
  2493. doBuildExprEvaluate(ctx, expr, tgt);
  2494. return;
  2495. case no_thor:
  2496. throwUnexpected();
  2497. // assertex(expr->queryType()->isScalar());
  2498. // buildExpr(ctx, expr->queryChild(0), tgt);
  2499. return;
  2500. case no_count:
  2501. if (!(expr->isPure() && ctx.getMatchExpr(expr, tgt)))
  2502. doBuildExprCount(ctx, expr, tgt);
  2503. return;
  2504. case no_max:
  2505. case no_min:
  2506. case no_sum:
  2507. if (!(expr->isPure() && ctx.getMatchExpr(expr, tgt)))
  2508. doBuildExprAggregate(ctx, expr, tgt);
  2509. return;
  2510. case no_exists:
  2511. if (!(expr->isPure() && ctx.getMatchExpr(expr, tgt)))
  2512. doBuildExprExists(ctx, expr, tgt);
  2513. return;
  2514. case no_existslist:
  2515. doBuildAggregateList(ctx, NULL, expr, &tgt);
  2516. return;
  2517. case no_countlist:
  2518. doBuildAggregateList(ctx, NULL, expr, &tgt);
  2519. return;
  2520. case no_sumlist:
  2521. doBuildAggregateList(ctx, NULL, expr, &tgt);
  2522. return;
  2523. case no_minlist:
  2524. doBuildAggregateList(ctx, NULL, expr, &tgt);
  2525. return;
  2526. case no_maxlist:
  2527. doBuildAggregateList(ctx, NULL, expr, &tgt);
  2528. return;
  2529. case no_sizeof:
  2530. doBuildExprSizeof(ctx, expr, tgt);
  2531. return;
  2532. case no_filepos:
  2533. doBuildExprFilepos(ctx, expr, tgt);
  2534. return;
  2535. case no_file_logicalname:
  2536. doBuildExprFileLogicalName(ctx, expr, tgt);
  2537. return;
  2538. case no_getresult:
  2539. case no_workunit_dataset:
  2540. doBuildExprGetResult(ctx, expr, tgt);
  2541. return;
  2542. case no_getgraphresult:
  2543. doBuildExprGetGraphResult(ctx, expr, tgt, FormatNatural);
  2544. return;
  2545. case no_regex_find:
  2546. case no_regex_replace:
  2547. doBuildExprRegexFindReplace(ctx, expr, tgt);
  2548. return;
  2549. case no_skip:
  2550. case no_assert:
  2551. {
  2552. buildStmt(ctx, expr);
  2553. OwnedHqlExpr null = createNullExpr(expr);
  2554. buildExpr(ctx, null, tgt);
  2555. return;
  2556. }
  2557. case no_matched:
  2558. case no_matchtext:
  2559. case no_matchlength:
  2560. case no_matchposition:
  2561. case no_matchunicode:
  2562. case no_matchutf8:
  2563. doBuildMatched(ctx, NULL, expr, &tgt);
  2564. return;
  2565. case no_matchattr:
  2566. doBuildMatchAttr(ctx, NULL, expr, &tgt);
  2567. return;
  2568. case no_rowdiff:
  2569. doBuildExprRowDiff(ctx, expr, tgt);
  2570. return;
  2571. case no_xmltext:
  2572. doBuildExprXmlText(ctx, expr, tgt);
  2573. return;
  2574. case no_xmlunicode:
  2575. doBuildExprXmlUnicode(ctx, expr, tgt);
  2576. return;
  2577. case no_evalonce:
  2578. doBuildEvalOnce(ctx, NULL, expr, &tgt);
  2579. return;
  2580. case no_alias:
  2581. doBuildExprAlias(ctx, expr, &tgt);
  2582. return;
  2583. case no_alias_scope:
  2584. {
  2585. expandAliasScope(ctx, expr);
  2586. buildExpr(ctx, expr->queryChild(0), tgt);
  2587. return;
  2588. }
  2589. case no_between:
  2590. case no_notbetween:
  2591. {
  2592. OwnedHqlExpr between = expandBetween(expr);
  2593. buildExpr(ctx, between, tgt);
  2594. return;
  2595. }
  2596. case no_libraryinput:
  2597. doBuildAliasValue(ctx, expr, tgt);
  2598. return;
  2599. case no_externalcall:
  2600. case no_call:
  2601. doBuildExprCall(ctx, expr, tgt);
  2602. return;
  2603. case no_comma:
  2604. case no_compound:
  2605. buildStmt(ctx, expr->queryChild(0));
  2606. buildExpr(ctx, expr->queryChild(1), tgt);
  2607. return;
  2608. case no_cast:
  2609. case no_implicitcast:
  2610. doBuildExprCast(ctx, expr, tgt);
  2611. return;
  2612. case no_charlen:
  2613. tgt.expr.setown(doBuildCharLength(ctx, expr->queryChild(0)));
  2614. return;
  2615. case no_add:
  2616. doBuildExprAdd(ctx, expr, tgt);
  2617. return;
  2618. case no_mul:
  2619. case no_sub:
  2620. doBuildExprArith(ctx, expr, tgt);
  2621. return;
  2622. case no_abs:
  2623. doBuildExprAbs(ctx, expr, tgt);
  2624. return;
  2625. case no_negate:
  2626. doBuildExprNegate(ctx, expr, tgt);
  2627. return;
  2628. case no_div:
  2629. case no_modulus:
  2630. doBuildExprDivide(ctx, expr, tgt);
  2631. return;
  2632. case no_if:
  2633. doBuildExprIf(ctx, expr, tgt);
  2634. return;
  2635. case no_index:
  2636. doBuildExprIndex(ctx, expr, tgt);
  2637. return;
  2638. case no_list:
  2639. doBuildExprList(ctx, expr, tgt);
  2640. return;
  2641. case no_all:
  2642. doBuildExprAll(ctx, expr, tgt);
  2643. return;
  2644. case no_trim:
  2645. doBuildExprTrim(ctx, expr, tgt);
  2646. return;
  2647. case no_intformat:
  2648. doBuildExprFormat(intFormatAtom, ctx, expr, tgt);
  2649. return;
  2650. case no_realformat:
  2651. doBuildExprFormat(realFormatAtom, ctx, expr, tgt);
  2652. return;
  2653. case no_exp:
  2654. doBuildExprSysFunc(ctx, expr, tgt, clibExpIdAtom);
  2655. return;
  2656. case no_ln:
  2657. doBuildExprSysFunc(ctx, expr, tgt, lnAtom);
  2658. return;
  2659. case no_sin:
  2660. doBuildExprSysFunc(ctx, expr, tgt, sinAtom);
  2661. return;
  2662. case no_cos:
  2663. doBuildExprSysFunc(ctx, expr, tgt, cosAtom);
  2664. return;
  2665. case no_tan:
  2666. doBuildExprSysFunc(ctx, expr, tgt, tanAtom);
  2667. return;
  2668. case no_asin:
  2669. doBuildExprSysFunc(ctx, expr, tgt, asinAtom);
  2670. return;
  2671. case no_acos:
  2672. doBuildExprSysFunc(ctx, expr, tgt, acosAtom);
  2673. return;
  2674. case no_atan:
  2675. doBuildExprSysFunc(ctx, expr, tgt, atanAtom);
  2676. return;
  2677. case no_atan2:
  2678. doBuildExprSysFunc(ctx, expr, tgt, atan2Atom);
  2679. return;
  2680. case no_sinh:
  2681. doBuildExprSysFunc(ctx, expr, tgt, sinhAtom);
  2682. return;
  2683. case no_cosh:
  2684. doBuildExprSysFunc(ctx, expr, tgt, coshAtom);
  2685. return;
  2686. case no_tanh:
  2687. doBuildExprSysFunc(ctx, expr, tgt, tanhAtom);
  2688. return;
  2689. case no_log10:
  2690. doBuildExprSysFunc(ctx, expr, tgt, log10Atom);
  2691. return;
  2692. case no_power:
  2693. doBuildExprSysFunc(ctx, expr, tgt, powerAtom);
  2694. return;
  2695. case no_fail:
  2696. doBuildStmtFail(ctx, expr);
  2697. tgt.expr.setown(createConstant(0));
  2698. return;
  2699. case no_failcode:
  2700. doBuildExprFailCode(ctx, expr, tgt);
  2701. return;
  2702. case no_ordered:
  2703. doBuildExprOrdered(ctx, expr, tgt);
  2704. return;
  2705. case no_random:
  2706. doBuildExprSysFunc(ctx, expr, tgt, rtlRandomAtom);
  2707. return;
  2708. case no_recovering:
  2709. doBuildExprSysFunc(ctx, expr, tgt, getRecoveringCountAtom);
  2710. return;
  2711. case no_rank:
  2712. doBuildExprRank(ctx, expr, tgt);
  2713. return;
  2714. case no_ranked:
  2715. doBuildExprRanked(ctx, expr, tgt);
  2716. return;
  2717. case no_round:
  2718. case no_roundup:
  2719. doBuildExprRound(ctx, expr, tgt);
  2720. return;
  2721. case no_sqrt:
  2722. doBuildExprSysFunc(ctx, expr, tgt, sqrtAtom);
  2723. return;
  2724. case no_truncate:
  2725. doBuildExprTrunc(ctx, expr, tgt);
  2726. return;
  2727. case no_offsetof:
  2728. doBuildExprOffsetOf(ctx, expr, tgt);
  2729. return;
  2730. case no_substring:
  2731. doBuildExprSubString(ctx, expr, tgt);
  2732. return;
  2733. case no_in:
  2734. case no_notin:
  2735. {
  2736. if (expr->queryChild(1)->getOperator() == no_all)
  2737. tgt.expr.setown(createConstant(op == no_in));
  2738. else
  2739. {
  2740. OwnedHqlExpr optimized = querySimplifyInExpr(expr);
  2741. if (options.globalFold && optimized)
  2742. {
  2743. OwnedHqlExpr folded = foldHqlExpression(optimized);
  2744. buildExpr(ctx, folded, tgt);
  2745. }
  2746. else
  2747. buildTempExpr(ctx, expr, tgt);
  2748. }
  2749. return;
  2750. }
  2751. case no_case:
  2752. case no_choose:
  2753. case no_concat:
  2754. case no_crc:
  2755. case no_hash:
  2756. case no_hash32:
  2757. case no_hash64:
  2758. case no_hashmd5:
  2759. case no_map:
  2760. case no_order:
  2761. case no_unicodeorder:
  2762. case no_rejected:
  2763. case no_which:
  2764. case no_addsets:
  2765. case no_createset:
  2766. case no_catch:
  2767. case no_failmessage:
  2768. case no_eventname:
  2769. case no_eventextra:
  2770. case no_loopcounter:
  2771. case no_toxml:
  2772. buildTempExpr(ctx, expr, tgt);
  2773. return;
  2774. case no_asstring:
  2775. case no_typetransfer:
  2776. doBuildExprTransfer(ctx, expr, tgt);
  2777. return;
  2778. case no_translated:
  2779. {
  2780. expandTranslated(expr, tgt);
  2781. return;
  2782. }
  2783. case no_eq:
  2784. case no_ne:
  2785. case no_le:
  2786. case no_lt:
  2787. case no_ge:
  2788. case no_gt:
  2789. if (options.expressionPeephole)
  2790. {
  2791. OwnedHqlExpr optimized = peepholeOptimize(ctx, expr);
  2792. if (optimized != expr)
  2793. {
  2794. buildExpr(ctx, optimized, tgt);
  2795. return;
  2796. }
  2797. }
  2798. doBuildExprCompare(ctx, expr, tgt);
  2799. return;
  2800. case no_wuid:
  2801. doBuildExprWuid(ctx, expr, tgt);
  2802. return;
  2803. case no_getenv:
  2804. {
  2805. OwnedHqlExpr mapped = cvtGetEnvToCall(expr);
  2806. buildExpr(ctx, mapped, tgt);
  2807. return;
  2808. }
  2809. case no_notnot:
  2810. {
  2811. OwnedHqlExpr castChild = ensureExprType(expr->queryChild(0), queryBoolType());
  2812. buildExpr(ctx, castChild, tgt);
  2813. }
  2814. return;
  2815. case no_not:
  2816. {
  2817. IHqlExpression * child = expr->queryChild(0);
  2818. node_operator childOp = child->getOperator();
  2819. if (((childOp == no_and) || (childOp == no_or)) && requiresTempAfterFirst(ctx, child))
  2820. buildTempExpr(ctx, expr, tgt);
  2821. else
  2822. doBuildExprNot(ctx, expr, tgt);
  2823. return;
  2824. }
  2825. case no_constant:
  2826. {
  2827. ITypeInfo * type = expr->queryType();
  2828. if ((options.inlineStringThreshold > 0) && (type->getSize() > options.inlineStringThreshold) && (type->getSize() != UNKNOWN_LENGTH))
  2829. {
  2830. IHqlExpression * literal = addBigLiteral((const char *)expr->queryValue()->queryValue(), type->getSize());
  2831. Owned<ITypeInfo> retType = makeReferenceModifier(LINK(type));
  2832. switch (type->getTypeCode())
  2833. {
  2834. case type_unicode:
  2835. case type_varunicode:
  2836. case type_utf8:
  2837. literal = createValue(no_implicitcast, LINK(retType), literal);
  2838. break;
  2839. }
  2840. if (literal->queryType() != retType)
  2841. literal = createValue(no_typetransfer, LINK(retType), literal);
  2842. tgt.expr.setown(literal);
  2843. }
  2844. else
  2845. tgt.expr.set(expr);
  2846. return;
  2847. }
  2848. case no_quoted:
  2849. case no_variable:
  2850. tgt.expr.set(expr);
  2851. return;
  2852. case no_globalscope:
  2853. if (options.regressionTest)
  2854. throwUnexpected();
  2855. buildExpr(ctx, expr->queryChild(0), tgt);
  2856. return;
  2857. case no_nofold:
  2858. case no_nohoist:
  2859. case no_section:
  2860. case no_sectioninput:
  2861. case no_pure:
  2862. buildExpr(ctx, expr->queryChild(0), tgt);
  2863. return;
  2864. case no_band:
  2865. case no_bor:
  2866. case no_bnot:
  2867. case no_bxor:
  2868. case no_lshift:
  2869. case no_rshift:
  2870. doBuildPureSubExpr(ctx, expr, tgt);
  2871. return;
  2872. //MORE: Shouldn't these be special cased?
  2873. case no_xor:
  2874. doBuildPureSubExpr(ctx, expr, tgt);
  2875. return;
  2876. case no_select:
  2877. {
  2878. OwnedHqlExpr aggregate = convertToSimpleAggregate(expr);
  2879. if (aggregate && canProcessInline(&ctx, aggregate->queryChild(0)))
  2880. {
  2881. buildExpr(ctx, aggregate, tgt);
  2882. return;
  2883. }
  2884. Owned<IReferenceSelector> selector = buildReference(ctx, expr);
  2885. selector->get(ctx, tgt);
  2886. return;
  2887. }
  2888. case no_field:
  2889. throwUnexpected();
  2890. case no_is_null:
  2891. {
  2892. //Until we have something better in place isNull is the inverse of isValid().
  2893. IHqlExpression * child = expr->queryChild(0);
  2894. OwnedHqlExpr null = createValue(no_not, makeBoolType(), createValue(no_is_valid, makeBoolType(), LINK(child)));
  2895. buildExpr(ctx, null, tgt);
  2896. }
  2897. return;
  2898. case no_is_valid:
  2899. doBuildExprIsValid(ctx, expr, tgt);
  2900. return;
  2901. case no_fromunicode:
  2902. case no_tounicode:
  2903. doBuildExprToFromUnicode(ctx, expr, tgt);
  2904. return;
  2905. case no_keyunicode:
  2906. doBuildExprKeyUnicode(ctx, expr, tgt);
  2907. return;
  2908. case no_xmldecode:
  2909. case no_xmlencode:
  2910. buildTempExpr(ctx, expr, tgt);
  2911. return;
  2912. case no_and:
  2913. case no_or:
  2914. if (requiresTempAfterFirst(ctx, expr))
  2915. buildTempExpr(ctx, expr, tgt);
  2916. else
  2917. doBuildPureSubExpr(ctx, expr, tgt);
  2918. return;
  2919. case no_assertkeyed:
  2920. case no_assertwild:
  2921. {
  2922. StringBuffer s;
  2923. throwError1(HQLERR_KeyedWildNoIndex, getExprECL(expr, s).str());
  2924. }
  2925. case no_assertstepped:
  2926. {
  2927. StringBuffer s;
  2928. throwError1(HQLERR_SteppedNoJoin, getExprECL(expr, s).str());
  2929. }
  2930. case no_id2blob:
  2931. doBuildExprIdToBlob(ctx, expr, tgt);
  2932. return;
  2933. case no_blob2id:
  2934. doBuildExprBlobToId(ctx, expr, tgt);
  2935. return;
  2936. case no_cppbody:
  2937. doBuildExprCppBody(ctx, expr, &tgt);
  2938. return;
  2939. case no_null:
  2940. tgt.length.setown(getSizetConstant(0));
  2941. tgt.expr.setown(createValue(no_nullptr, makeReferenceModifier(expr->getType())));
  2942. return;
  2943. case no_clustersize:
  2944. doBuildExprSysFunc(ctx, expr, tgt, getClusterSizeAtom);
  2945. return;
  2946. case no_deref:
  2947. //Untested
  2948. buildExpr(ctx, expr->queryChild(0), tgt);
  2949. if (tgt.expr->getOperator() == no_address)
  2950. tgt.expr.setown(createValue(no_typetransfer, expr->getType(), LINK(tgt.expr->queryChild(0))));
  2951. else
  2952. tgt.expr.setown(createValue(no_deref, expr->getType(), LINK(tgt.expr)));
  2953. return;
  2954. case no_funcdef:
  2955. tgt.expr.setown(doBuildInternalFunction(expr));
  2956. useFunction(tgt.expr);
  2957. return;
  2958. case no_purevirtual:
  2959. case no_internalvirtual:
  2960. {
  2961. //This shouldn't happen we should have an no_checkconcrete wrapper inserted into the tree like checkconstant,
  2962. //but it currently can in obscure library contexts (e.g., library3ie2.xhql)
  2963. _ATOM name = expr->queryName();
  2964. throwError1(HQLERR_ConcreteMemberRequired, name ? name->str() : "");
  2965. }
  2966. case NO_AGGREGATEGROUP:
  2967. throwError1(HQLERR_OutsideGroupAggregate, getOpString(op));
  2968. default:
  2969. break;
  2970. }
  2971. StringBuffer msg;
  2972. msg.append("Unexpected operator '").append(getOpString(op)).append("' in: HqlCppTranslator::buildExpr(");
  2973. toECL(expr, msg, true);
  2974. // expr->toString(msg);
  2975. msg.append(")");
  2976. throw MakeStringException(HQLERR_UnexpectedOperator, "%s", msg.str());
  2977. doBuildPureSubExpr(ctx, expr, tgt);
  2978. }
  2979. void HqlCppTranslator::buildExprOrAssign(BuildCtx & ctx, const CHqlBoundTarget * target, IHqlExpression * expr, CHqlBoundExpr * tgt)
  2980. {
  2981. if (target)
  2982. buildExprAssign(ctx, *target, expr);
  2983. else if (tgt)
  2984. buildExpr(ctx, expr, *tgt);
  2985. else
  2986. buildStmt(ctx, expr);
  2987. }
  2988. bool HqlCppTranslator::specialCaseBoolReturn(BuildCtx & ctx, IHqlExpression * expr)
  2989. {
  2990. if (!options.optimizeBoolReturn)
  2991. return false;
  2992. if ((expr->getOperator() == no_and) && (unwoundCount(expr, no_and) <= MAX_NESTED_CASES))
  2993. return true;
  2994. if (expr->getOperator() == no_not)
  2995. expr = expr->queryChild(0);
  2996. if (!requiresTemp(ctx, expr, true))
  2997. return false;
  2998. if (expr->getOperator() == no_alias_scope)
  2999. expr = expr->queryChild(0);
  3000. if ((expr->getOperator() == no_and) || (expr->getOperator() == no_or))
  3001. return true;
  3002. return false;
  3003. }
  3004. void HqlCppTranslator::buildReturn(BuildCtx & ctx, IHqlExpression * expr, ITypeInfo * retType)
  3005. {
  3006. ITypeInfo * exprType = expr->queryType();
  3007. if (!retType) retType = exprType;
  3008. expr = queryExpandAliasScope(ctx, expr);
  3009. node_operator op = expr->getOperator();
  3010. if ((retType->getSize() == UNKNOWN_LENGTH) && (retType->getTypeCode() == type_varstring))
  3011. {
  3012. if (hasConstModifier(retType) && (hasConstModifier(exprType) || expr->queryValue()))
  3013. {
  3014. OwnedHqlExpr cast = ensureExprType(expr, retType);
  3015. CHqlBoundExpr ret;
  3016. buildCachedExpr(ctx, cast, ret);
  3017. ctx.setNextDestructor();
  3018. ctx.addReturn(ret.expr);
  3019. }
  3020. else
  3021. {
  3022. if (hasConstModifier(retType))
  3023. {
  3024. BuildCtx * declareCtx = NULL;
  3025. if (getInvariantMemberContext(ctx, &declareCtx, NULL, false, false))
  3026. {
  3027. CHqlBoundTarget tempTarget;
  3028. createTempFor(*declareCtx, retType, tempTarget, typemod_member, FormatNatural);
  3029. buildExprAssign(ctx, tempTarget, expr);
  3030. OwnedHqlExpr result = getElementPointer(tempTarget.expr);
  3031. ctx.addReturn(result);
  3032. return;
  3033. }
  3034. //we are going to have a memory leak......
  3035. PrintLog("Runtime memory leak returning allocated string from constant function");
  3036. }
  3037. CHqlBoundTarget retVar;
  3038. retVar.expr.setown(createWrapperTemp(ctx, retType, typemod_none));
  3039. buildExprAssign(ctx, retVar, expr);
  3040. ctx.setNextDestructor();
  3041. StringBuffer s;
  3042. retVar.expr->toString(s);
  3043. switch (retType->getTypeCode())
  3044. {
  3045. case type_varstring:
  3046. s.append(".detachstr()");
  3047. break;
  3048. case type_varunicode:
  3049. s.append(".detachustr()");
  3050. break;
  3051. default:
  3052. UNIMPLEMENTED;
  3053. }
  3054. OwnedHqlExpr temp = createQuoted(s.str(), LINK(exprType));
  3055. ctx.addReturn(temp);
  3056. }
  3057. }
  3058. else if ((retType->getTypeCode() == type_boolean) && specialCaseBoolReturn(ctx, expr))
  3059. {
  3060. bool successValue = true;
  3061. if (op == no_not)
  3062. {
  3063. //!(a and b) is converted into !a || !b. Otherwise just invert the test condition.
  3064. IHqlExpression * child = expr->queryChild(0);
  3065. if (child->getOperator() == no_alias_scope)
  3066. child = child->queryChild(0);
  3067. if (child->getOperator() != no_and)
  3068. {
  3069. successValue = false;
  3070. expr = expr->queryChild(0);
  3071. }
  3072. }
  3073. BuildCtx condctx(ctx);
  3074. buildFilteredReturn(condctx, expr, queryBoolExpr(successValue));
  3075. buildReturn(ctx, queryBoolExpr(!successValue));
  3076. }
  3077. else if (op == no_if)
  3078. {
  3079. OwnedHqlExpr castTrue = ensureExprType(expr->queryChild(1), retType);
  3080. OwnedHqlExpr castFalse = ensureExprType(expr->queryChild(2), retType);
  3081. BuildCtx condctx(ctx);
  3082. buildFilter(condctx, expr->queryChild(0));
  3083. buildReturn(condctx, castTrue);
  3084. buildReturn(ctx, castFalse);
  3085. }
  3086. else if (op == no_map || op == no_case)
  3087. {
  3088. HqlCppCaseInfo info(*this);
  3089. doBuildCaseInfo(expr, info);
  3090. info.buildReturn(ctx);
  3091. }
  3092. else
  3093. {
  3094. CHqlBoundExpr ret;
  3095. // A very temporary work around for potential gpf using variable length strings
  3096. OwnedHqlExpr castExpr = ensureExprType(expr, retType);
  3097. buildSimpleExpr(ctx, castExpr, ret);
  3098. ctx.setNextDestructor();
  3099. ctx.addReturn(ret.expr);
  3100. }
  3101. }
  3102. //Assumes that the value being returned is simple.
  3103. //for (a || b || c) gen if (a) return x; if (b) return x; if (c) return x;
  3104. //and !(a && b && c) -> !a || !b || !c
  3105. void HqlCppTranslator::buildFilteredReturn(BuildCtx & ctx, IHqlExpression * filter, IHqlExpression * value)
  3106. {
  3107. filter = queryExpandAliasScope(ctx, filter);
  3108. HqlExprArray conds;
  3109. node_operator op = filter->getOperator();
  3110. if (op == no_or)
  3111. {
  3112. buildFilteredReturn(ctx, filter->queryChild(0), value);
  3113. buildFilteredReturn(ctx, filter->queryChild(1), value);
  3114. return;
  3115. }
  3116. if (op == no_not)
  3117. {
  3118. IHqlExpression * child = filter->queryChild(0);
  3119. node_operator childOp = child->getOperator();
  3120. if (childOp == no_and)
  3121. {
  3122. child->unwindList(conds, no_and);
  3123. ForEachItemIn(i, conds)
  3124. {
  3125. IHqlExpression & cur = conds.item(i);
  3126. OwnedHqlExpr inverse = getInverse(&cur);
  3127. buildFilteredReturn(ctx, inverse, value);
  3128. }
  3129. return;
  3130. }
  3131. if (childOp == no_alias_scope)
  3132. {
  3133. expandAliasScope(ctx, child);
  3134. OwnedHqlExpr inverse = getInverse(child->queryChild(0));
  3135. buildFilteredReturn(ctx, inverse, value);
  3136. return;
  3137. }
  3138. }
  3139. BuildCtx condctx(ctx);
  3140. buildFilter(condctx, filter);
  3141. if (value)
  3142. buildReturn(condctx, value);
  3143. else
  3144. condctx.addReturn(NULL);
  3145. }
  3146. void HqlCppTranslator::buildStmt(BuildCtx & _ctx, IHqlExpression * expr)
  3147. {
  3148. BuildCtx ctx(_ctx);
  3149. switch (expr->getOperator())
  3150. {
  3151. case no_assign:
  3152. doBuildStmtAssign(ctx, expr->queryChild(0), expr->queryChild(1));
  3153. return;
  3154. case no_assign_addfiles:
  3155. doBuildStmtAssignModify(ctx, expr->queryChild(0), expr->queryChild(1), expr->getOperator());
  3156. return;
  3157. case no_alias:
  3158. doBuildExprAlias(ctx, expr, NULL);
  3159. return;
  3160. case no_alias_scope:
  3161. {
  3162. expandAliasScope(ctx, expr);
  3163. buildStmt(ctx, expr->queryChild(0));
  3164. return;
  3165. }
  3166. case no_assignall:
  3167. {
  3168. unsigned idx;
  3169. unsigned kids = expr->numChildren();
  3170. for (idx = 0; idx < kids; idx++)
  3171. buildStmt(ctx, expr->queryChild(idx));
  3172. return;
  3173. }
  3174. case no_comma:
  3175. case no_compound:
  3176. buildStmt(ctx, expr->queryChild(0));
  3177. buildStmt(ctx, expr->queryChild(1));
  3178. return;
  3179. case no_if:
  3180. doBuildStmtIf(ctx, expr);
  3181. return;
  3182. case no_call:
  3183. case no_externalcall:
  3184. doBuildStmtCall(ctx, expr);
  3185. return;
  3186. case no_nofold:
  3187. case no_nohoist:
  3188. case no_nothor:
  3189. case no_section:
  3190. case no_sectioninput:
  3191. buildStmt(ctx, expr->queryChild(0));
  3192. return;
  3193. case no_null:
  3194. return;
  3195. case no_fail:
  3196. doBuildStmtFail(ctx, expr);
  3197. return;
  3198. case no_setmeta:
  3199. return;
  3200. case no_update:
  3201. doBuildStmtUpdate(ctx, expr);
  3202. return;
  3203. case no_output:
  3204. if (queryRealChild(expr, 1))
  3205. throwError1(HQLERR_NotSupportedInsideNoThor, "OUTPUT to file");
  3206. doBuildStmtOutput(ctx, expr);
  3207. return;
  3208. case no_subgraph:
  3209. doBuildThorChildSubGraph(ctx, expr, SubGraphRoot);
  3210. return;
  3211. case no_thor:
  3212. doBuildThorGraph(ctx, expr);
  3213. return;
  3214. case no_workflow_action:
  3215. return;
  3216. case no_ensureresult:
  3217. doBuildStmtEnsureResult(ctx, expr);
  3218. return;
  3219. case no_extractresult:
  3220. case no_setresult:
  3221. doBuildStmtSetResult(ctx, expr);
  3222. return;
  3223. case no_parallel:
  3224. case no_sequential:
  3225. case no_actionlist:
  3226. {
  3227. ForEachChild(idx, expr)
  3228. buildStmt(ctx, expr->queryChild(idx));
  3229. return;
  3230. }
  3231. case no_wait:
  3232. doBuildStmtWait(ctx, expr);
  3233. return;
  3234. case no_notify:
  3235. doBuildStmtNotify(ctx, expr);
  3236. return;
  3237. case no_skip:
  3238. doBuildStmtSkip(ctx, expr, NULL);
  3239. return;
  3240. case no_assert:
  3241. doBuildStmtAssert(ctx, expr);
  3242. return;
  3243. case no_cppbody:
  3244. doBuildExprCppBody(ctx, expr, NULL);
  3245. return;
  3246. case no_setworkflow_cond:
  3247. {
  3248. HqlExprArray args;
  3249. args.append(*LINK(expr->queryChild(0)));
  3250. buildFunctionCall(ctx, setWorkflowConditionAtom, args);
  3251. return;
  3252. }
  3253. case no_apply:
  3254. doBuildStmtApply(ctx, expr);
  3255. return;
  3256. case no_cluster:
  3257. doBuildStmtCluster(ctx, expr);
  3258. return;
  3259. case no_choose:
  3260. doBuildChoose(ctx, NULL, expr);
  3261. return;
  3262. case no_persist_check:
  3263. buildWorkflowPersistCheck(ctx, expr);
  3264. return;
  3265. case no_evaluate_stmt:
  3266. expr = expr->queryChild(0);
  3267. if (expr->queryValue())
  3268. return;
  3269. // fall through to default behaviour.
  3270. }
  3271. CHqlBoundExpr tgt;
  3272. buildAnyExpr(ctx, expr, tgt);
  3273. ctx.addExpr(tgt.expr);
  3274. tidyupExpr(ctx, tgt);
  3275. }
  3276. class AliasExpansionInfo
  3277. {
  3278. public:
  3279. void pushCondition(IHqlExpression * expr, unsigned branch) { conditions.append(*createAttribute(branchAtom, LINK(expr), getSizetConstant(branch))); }
  3280. void popCondition() { conditions.pop(); }
  3281. void popConditions(unsigned num) { conditions.popn(num); }
  3282. bool isConditional() { return conditions.ordinality() != 0; }
  3283. IHqlExpression * createConditionIntersection(IHqlExpression * prev)
  3284. {
  3285. if (conditions.ordinality() == 0)
  3286. return NULL;
  3287. if (!prev)
  3288. return createValueSafe(no_sortlist, makeSortListType(NULL), conditions);
  3289. unsigned maxPrev = prev->numChildren();
  3290. unsigned max = maxPrev;
  3291. if (max > conditions.ordinality())
  3292. max = conditions.ordinality();
  3293. for (unsigned i=0; i < max; i++)
  3294. {
  3295. if (&conditions.item(i) != prev->queryChild(i))
  3296. {
  3297. if (i == 0)
  3298. return NULL;
  3299. return createValueSafe(no_sortlist, makeSortListType(NULL), conditions, 0, i);
  3300. }
  3301. }
  3302. if (max == maxPrev)
  3303. return LINK(prev);
  3304. return createValueSafe(no_sortlist, makeSortListType(NULL), conditions);
  3305. }
  3306. HqlExprArray conditions;
  3307. };
  3308. void HqlCppTranslator::doExpandAliases(BuildCtx & ctx, IHqlExpression * expr, AliasExpansionInfo & info)
  3309. {
  3310. IHqlExpression * prev = static_cast<IHqlExpression *>(expr->queryTransformExtra());
  3311. if (prev == expr)
  3312. return;
  3313. #ifdef USE_NEW_ALIAS_CODE
  3314. OwnedHqlExpr commonPath = info.createConditionIntersection(prev);
  3315. if (prev == commonPath)
  3316. return;
  3317. if (commonPath)
  3318. expr->setTransformExtra(commonPath);
  3319. else
  3320. expr->setTransformExtraUnlinked(expr);
  3321. node_operator op = expr->getOperator();
  3322. switch (op)
  3323. {
  3324. //MORE: Anything that creates a child query shouldn't be included here...
  3325. case no_select:
  3326. case NO_AGGREGATE:
  3327. case no_alias_scope:
  3328. break;
  3329. case no_alias:
  3330. {
  3331. IHqlExpression * value = expr->queryChild(0);
  3332. if ((commonPath == NULL) && !ctx.queryMatchExpr(value))
  3333. {
  3334. if (containsAliasLocally(value) && !expr->hasProperty(globalAtom))
  3335. doExpandAliases(ctx, value, info);
  3336. doBuildExprAlias(ctx, expr, NULL);
  3337. }
  3338. break;
  3339. }
  3340. case no_and:
  3341. case no_or:
  3342. {
  3343. HqlExprArray args;
  3344. expr->unwindList(args, op);
  3345. doExpandAliases(ctx, &args.item(0), info);
  3346. unsigned max = args.ordinality();
  3347. for (unsigned i=1; i < max; i++)
  3348. {
  3349. info.pushCondition(expr, i);
  3350. doExpandAliases(ctx, &args.item(i), info);
  3351. }
  3352. info.popConditions(max-1);
  3353. break;
  3354. }
  3355. case no_if:
  3356. {
  3357. doExpandAliases(ctx, expr->queryChild(0), info);
  3358. info.pushCondition(expr, 1);
  3359. doExpandAliases(ctx, expr->queryChild(1), info);
  3360. info.popCondition();
  3361. info.pushCondition(expr, 2);
  3362. doExpandAliases(ctx, expr->queryChild(2), info);
  3363. info.popCondition();
  3364. break;
  3365. }
  3366. case no_case:
  3367. {
  3368. doExpandAliases(ctx, expr->queryChild(0), info);
  3369. unsigned max = expr->numChildren();
  3370. for (unsigned i=1; i < max-1; i++)
  3371. {
  3372. info.pushCondition(expr, i*2);
  3373. doExpandAliases(ctx, expr->queryChild(i)->queryChild(0), info);
  3374. info.popCondition();
  3375. info.pushCondition(expr, i*2+1);
  3376. doExpandAliases(ctx, expr->queryChild(i)->queryChild(1), info);
  3377. info.popCondition();
  3378. }
  3379. info.pushCondition(expr, (max-1)*2);
  3380. doExpandAliases(ctx, expr->queryChild(max-1), info);
  3381. info.popCondition();
  3382. break;
  3383. }
  3384. case no_map:
  3385. {
  3386. //The following is equivalent to old, code; I'm not sure it is the best implementation
  3387. unsigned max = expr->numChildren();
  3388. for (unsigned i=0; i < max-1; i++)
  3389. {
  3390. info.pushCondition(expr, i*2);
  3391. doExpandAliases(ctx, expr->queryChild(i)->queryChild(0), info);
  3392. info.popCondition();
  3393. info.pushCondition(expr, i*2+1);
  3394. doExpandAliases(ctx, expr->queryChild(i)->queryChild(1), info);
  3395. info.popCondition();
  3396. }
  3397. info.pushCondition(expr, (max-1)*2);
  3398. doExpandAliases(ctx, expr->queryChild(max-1), info);
  3399. info.popCondition();
  3400. break;
  3401. }
  3402. default:
  3403. if (containsAliasLocally(expr))
  3404. {
  3405. ForEachChild(i, expr)
  3406. doExpandAliases(ctx, expr->queryChild(i), info);
  3407. }
  3408. break;
  3409. }
  3410. #else
  3411. expr->setTransformExtraUnlinked(expr);
  3412. node_operator op = expr->getOperator();
  3413. switch (op)
  3414. {
  3415. //MORE: Anything that creates a child query shouldn't be included here...
  3416. case no_select:
  3417. case NO_AGGREGATE:
  3418. case no_alias_scope:
  3419. break;
  3420. case no_alias:
  3421. {
  3422. doBuildExprAlias(ctx, expr, NULL);
  3423. break;
  3424. }
  3425. default:
  3426. if (containsAliasLocally(expr))
  3427. {
  3428. ForEachChild(i, expr)
  3429. doExpandAliases(ctx, expr->queryChild(i), info);
  3430. }
  3431. break;
  3432. }
  3433. #endif
  3434. }
  3435. void HqlCppTranslator::expandAliases(BuildCtx & ctx, IHqlExpression * expr)
  3436. {
  3437. if (containsAliasLocally(expr))
  3438. {
  3439. TransformMutexBlock block;
  3440. AliasExpansionInfo info;
  3441. doExpandAliases(ctx, expr, info);
  3442. }
  3443. }
  3444. void HqlCppTranslator::expandAliasScope(BuildCtx & ctx, IHqlExpression * expr)
  3445. {
  3446. TransformMutexBlock block;
  3447. AliasExpansionInfo info;
  3448. unsigned max = expr->numChildren();
  3449. for (unsigned idx = 1; idx < max; idx++)
  3450. {
  3451. IHqlExpression * child = expr->queryChild(idx);
  3452. if (containsAliasLocally(child))
  3453. doExpandAliases(ctx, child, info);
  3454. }
  3455. }
  3456. //------------------------------------------------------------------------------
  3457. void HqlCppTranslator::gatherActiveCursors(BuildCtx & ctx, HqlExprCopyArray & activeRows)
  3458. {
  3459. AssociationIterator iter(ctx);
  3460. ForEach(iter)
  3461. {
  3462. HqlExprAssociation & cur = iter.get();
  3463. if (cur.isRowAssociation())
  3464. {
  3465. BoundRow & curRow = static_cast<BoundRow &>(cur);
  3466. if ((curRow.querySide() != no_self) && !curRow.isBuilder())
  3467. activeRows.append(*curRow.querySelector());
  3468. }
  3469. else if (cur.represents->getOperator() == no_counter)
  3470. activeRows.append(*cur.represents);
  3471. }
  3472. }
  3473. bool HqlCppTranslator::canEvaluateInContext(BuildCtx & ctx, IHqlExpression * expr)
  3474. {
  3475. HqlExprCopyArray cursors;
  3476. gatherActiveCursors(ctx, cursors);
  3477. return ::canEvaluateInScope(cursors, expr);
  3478. }
  3479. bool mustEvaluateInContext(BuildCtx & ctx, IHqlExpression * expr)
  3480. {
  3481. HqlExprCopyArray required;
  3482. expr->gatherTablesUsed(NULL, &required);
  3483. if (required.ordinality() == 0)
  3484. return false;
  3485. HqlExprCopyArray activeRows;
  3486. HqlExprCopyArray inheritedRows;
  3487. RowAssociationIterator iter(ctx);
  3488. ForEach(iter)
  3489. {
  3490. BoundRow & cur = iter.get();
  3491. if ((cur.querySide() != no_self) && !cur.isBuilder())
  3492. {
  3493. IHqlExpression * selector = cur.querySelector();
  3494. if (cur.isInherited())
  3495. inheritedRows.append(*selector);
  3496. else
  3497. activeRows.append(*selector);
  3498. }
  3499. }
  3500. //Ensure all instances of activeRows which match the inherited rows are removed
  3501. ForEachItemInRev(i, activeRows)
  3502. {
  3503. if (inheritedRows.find(activeRows.item(i)))
  3504. activeRows.remove(i);
  3505. }
  3506. return canEvaluateInScope(activeRows, required);
  3507. }
  3508. bool filterIsTableInvariant(IHqlExpression * expr)
  3509. {
  3510. IHqlExpression * dsSelector = expr->queryChild(0)->queryNormalizedSelector();
  3511. ForEachChildFrom(i, expr, 1)
  3512. {
  3513. IHqlExpression * cur = expr->queryChild(i);
  3514. if (containsSelector(cur, dsSelector))
  3515. return false;
  3516. }
  3517. return true;
  3518. }
  3519. //-----------------------------------------------------------------------------
  3520. bool LoopInvariantHelper::getBestContext(BuildCtx & ctx, IHqlExpression * expr)
  3521. {
  3522. finished();
  3523. active = ctx.selectBestContext(expr);
  3524. return (active != NULL);
  3525. }
  3526. void LoopInvariantHelper::finished()
  3527. {
  3528. if (active)
  3529. {
  3530. active->mergeScopeWithContainer();
  3531. active = NULL;
  3532. }
  3533. }
  3534. //---------------------------------------------------------------------------
  3535. void HqlCppTranslator::buildBlockCopy(BuildCtx & ctx, IHqlExpression * tgt, CHqlBoundExpr & src)
  3536. {
  3537. OwnedHqlExpr size = getBoundSize(src);
  3538. if (!size->queryValue() || size->queryValue()->getIntValue() != 0)
  3539. {
  3540. HqlExprArray args;
  3541. args.append(*getPointer(tgt));
  3542. args.append(*getPointer(src.expr));
  3543. args.append(*size.getClear());
  3544. callProcedure(ctx, memcpyAtom, args);
  3545. }
  3546. }
  3547. void HqlCppTranslator::buildSimpleExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  3548. {
  3549. node_operator op = expr->getOperator();
  3550. bool simple = false;
  3551. switch (op)
  3552. {
  3553. case no_alias_scope:
  3554. {
  3555. expandAliasScope(ctx, expr);
  3556. buildSimpleExpr(ctx, expr->queryChild(0), tgt);
  3557. return;
  3558. }
  3559. case no_preservemeta:
  3560. buildSimpleExpr(ctx, expr->queryChild(0), tgt);
  3561. return;
  3562. case no_constant:
  3563. case no_variable:
  3564. case no_getresult: // gets forced into a variable.
  3565. case no_workunit_dataset: // gets forced into a variable.
  3566. case no_getgraphresult: // gets forced into a variable.
  3567. case no_alias:
  3568. case no_list:
  3569. case no_all:
  3570. case no_null:
  3571. case no_id2blob:
  3572. case no_rows:
  3573. case no_libraryinput:
  3574. simple = true;
  3575. break;
  3576. case no_compound:
  3577. buildStmt(ctx, expr->queryChild(0));
  3578. buildSimpleExpr(ctx, expr->queryChild(1), tgt);
  3579. return;
  3580. case no_field:
  3581. throwUnexpected();
  3582. case no_select:
  3583. {
  3584. CHqlBoundExpr bound;
  3585. buildCachedExpr(ctx, expr, bound);
  3586. if (isSimpleTranslatedExpr(bound.expr))
  3587. tgt.set(bound);
  3588. else
  3589. {
  3590. OwnedHqlExpr trans = bound.getTranslatedExpr();
  3591. buildTempExpr(ctx, trans, tgt);
  3592. }
  3593. return;
  3594. }
  3595. break; // should depend on whether conditional etc....
  3596. case no_translated:
  3597. simple = isSimpleTranslatedExpr(expr->queryChild(0));
  3598. break;
  3599. case no_substring:
  3600. {
  3601. SubStringInfo info(expr);
  3602. if (info.canGenerateInline() || expr->hasProperty(quickAtom))
  3603. simple = true;
  3604. break;
  3605. }
  3606. case no_cast:
  3607. case no_implicitcast:
  3608. {
  3609. //special case casting a string to (string) - saves lots of temporaries.
  3610. ITypeInfo * exprType = expr->queryType();
  3611. IHqlExpression * child = expr->queryChild(0);
  3612. ITypeInfo * childType = child->queryType();
  3613. if ((exprType->getTypeCode() == type_string) && (exprType->getSize() == UNKNOWN_LENGTH))
  3614. {
  3615. if ((childType->getTypeCode() == type_string) && (exprType->queryCharset() == childType->queryCharset()))
  3616. {
  3617. buildSimpleExpr(ctx, child, tgt);
  3618. return;
  3619. }
  3620. }
  3621. if (options.foldConstantCast && (child->getOperator() == no_constant))
  3622. simple = true;
  3623. break;
  3624. }
  3625. case no_sizeof:
  3626. case no_offsetof:
  3627. simple = true;
  3628. break;
  3629. case no_regex_find:
  3630. simple = expr->isBoolean();
  3631. break;
  3632. case no_call:
  3633. case no_externalcall:
  3634. {
  3635. ITypeInfo * type = expr->queryType();
  3636. switch (type->getTypeCode())
  3637. {
  3638. case type_set:
  3639. simple = true;
  3640. break;
  3641. case type_string:
  3642. case type_data:
  3643. case type_qstring:
  3644. if (type->getSize() == UNKNOWN_LENGTH)
  3645. simple = true;
  3646. break;
  3647. }
  3648. }
  3649. }
  3650. if (simple)
  3651. buildCachedExpr(ctx, expr, tgt);
  3652. else
  3653. buildTempExpr(ctx, expr, tgt);
  3654. }
  3655. IHqlExpression * HqlCppTranslator::buildSimplifyExpr(BuildCtx & ctx, IHqlExpression * expr)
  3656. {
  3657. node_operator op = expr->getOperator();
  3658. switch (op)
  3659. {
  3660. case no_constant:
  3661. case no_all:
  3662. case no_null:
  3663. return LINK(expr);
  3664. case no_list:
  3665. if (expr->isConstant())
  3666. return LINK(expr);
  3667. break;
  3668. }
  3669. CHqlBoundExpr bound;
  3670. buildSimpleExpr(ctx, expr, bound);
  3671. return bound.getTranslatedExpr();
  3672. }
  3673. /* In type: not linked. Return: linked */
  3674. IHqlExpression * HqlCppTranslator::createWrapperTemp(BuildCtx & ctx, ITypeInfo * type, typemod_t modifier)
  3675. {
  3676. Linked<ITypeInfo> rawType = queryUnqualifiedType(type);
  3677. if (hasLinkCountedModifier(type))
  3678. rawType.setown(makeAttributeModifier(rawType.getClear(), getLinkCountedAttr()));
  3679. Owned<ITypeInfo> declType = makeWrapperModifier(rawType.getClear());
  3680. declType.setown(makeModifier(declType.getClear(), modifier));
  3681. switch (declType->getTypeCode())
  3682. {
  3683. case type_set: //needed if we have sets with link counted elements
  3684. case type_row:
  3685. case type_array:
  3686. case type_table:
  3687. case type_groupedtable:
  3688. //Ensure row and dataset temporaries are active throughout a function, so pointers to the row
  3689. //or rows within a dataset remain valid (e.g., outside conditions).
  3690. if ((modifier != typemod_member) && ctx.queryMatchExpr(queryConditionalRowMarker()))
  3691. ctx.setNextPriority(BuildCtx::OutermostScopePrio);
  3692. break;
  3693. }
  3694. return ctx.getTempDeclare(declType, NULL);
  3695. }
  3696. void HqlCppTranslator::createTempFor(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundTarget & target)
  3697. {
  3698. createTempFor(ctx, expr->queryType(), target, typemod_none, FormatNatural);
  3699. }
  3700. void HqlCppTranslator::createTempFor(BuildCtx & ctx, ITypeInfo * _exprType, CHqlBoundTarget & target, typemod_t modifier, ExpressionFormat format)
  3701. {
  3702. Owned<ITypeInfo> exprType = makeModifier(LINK(_exprType->queryPromotedType()), modifier);
  3703. type_t tc = exprType->getTypeCode();
  3704. switch (tc)
  3705. {
  3706. case type_array:
  3707. case type_table:
  3708. case type_groupedtable:
  3709. {
  3710. if (recordRequiresSerialization(::queryRecord(exprType)) || hasLinkCountedModifier(_exprType))
  3711. {
  3712. assertex(format != FormatBlockedDataset);
  3713. format = FormatLinkedDataset;
  3714. }
  3715. else if (options.tempDatasetsUseLinkedRows && (format == FormatNatural))
  3716. format = FormatLinkedDataset;
  3717. break;
  3718. }
  3719. }
  3720. if (hasLinkCountedModifier(exprType))
  3721. {
  3722. if (format == FormatNatural)
  3723. format = FormatLinkedDataset;
  3724. else if (format == FormatBlockedDataset)
  3725. exprType.setown(setLinkCountedAttr(exprType, false));
  3726. }
  3727. else
  3728. {
  3729. if (format == FormatNatural)
  3730. format = FormatBlockedDataset;
  3731. else if ((format == FormatLinkedDataset) || (format == FormatArrayDataset))
  3732. exprType.setown(setLinkCountedAttr(exprType, true));
  3733. }
  3734. size32_t size = exprType->getSize();
  3735. if (size == UNKNOWN_LENGTH)
  3736. {
  3737. switch (tc)
  3738. {
  3739. case type_string:
  3740. case type_data:
  3741. case type_qstring:
  3742. case type_unicode:
  3743. case type_utf8:
  3744. {
  3745. OwnedITypeInfo lenType = makeModifier(LINK(sizetType), modifier);
  3746. target.expr.setown(createWrapperTemp(ctx, exprType, modifier));
  3747. target.length.setown(ctx.getTempDeclare(lenType, NULL));
  3748. break;
  3749. }
  3750. case type_varstring:
  3751. case type_varunicode:
  3752. {
  3753. target.expr.setown(createWrapperTemp(ctx, exprType, modifier));
  3754. break;
  3755. }
  3756. case type_set:
  3757. case type_array:
  3758. case type_table:
  3759. case type_groupedtable:
  3760. break;
  3761. default:
  3762. {
  3763. UNIMPLEMENTED;
  3764. break;
  3765. }
  3766. }
  3767. }
  3768. else if (size > MAX_SIMPLE_VAR_SIZE)
  3769. {
  3770. switch (tc)
  3771. {
  3772. case type_string:
  3773. case type_data:
  3774. case type_qstring:
  3775. case type_unicode:
  3776. case type_varstring:
  3777. case type_varunicode:
  3778. case type_utf8:
  3779. {
  3780. target.expr.setown(createWrapperTemp(ctx, exprType, modifier));
  3781. break;
  3782. }
  3783. }
  3784. }
  3785. switch (tc)
  3786. {
  3787. case type_set:
  3788. {
  3789. OwnedITypeInfo isAllType = makeModifier(LINK(boolType), modifier);
  3790. target.isAll.setown(ctx.getTempDeclare(isAllType, NULL));
  3791. }
  3792. //fall through
  3793. case type_array:
  3794. case type_table:
  3795. case type_groupedtable:
  3796. {
  3797. OwnedITypeInfo lenType = makeModifier(LINK(sizetType), modifier);
  3798. target.expr.setown(createWrapperTemp(ctx, exprType, modifier));
  3799. if (isArrayRowset(exprType))
  3800. {
  3801. //A bit of a hack, but the cleanest I could come up with... really access to the count member should be wrapped in
  3802. //member functions, but getting them created needs a whole new level of complication (probably moving out out of hqlwcpp)
  3803. StringBuffer name;
  3804. target.expr->toString(name).append(".count");
  3805. target.count.setown(createVariable(name, LINK(lenType)));
  3806. }
  3807. else
  3808. target.length.setown(ctx.getTempDeclare(lenType, NULL));
  3809. break;
  3810. }
  3811. }
  3812. if (!target.expr)
  3813. {
  3814. target.expr.setown(ctx.getTempDeclare(exprType, NULL));
  3815. }
  3816. }
  3817. void HqlCppTranslator::buildTempExpr(BuildCtx & ctx, BuildCtx & declareCtx, CHqlBoundTarget & tempTarget, IHqlExpression * expr, ExpressionFormat format, bool ignoreSetAll)
  3818. {
  3819. if (options.addLocationToCpp)
  3820. {
  3821. IHqlExpression * location = queryLocation(expr);
  3822. if (location)
  3823. {
  3824. StringBuffer s;
  3825. s.append("// ").append(location->querySourcePath()->str()).append("(").append(location->getStartLine()).append(",").append(location->getStartColumn()).append(") ").append(expr->queryName());
  3826. ctx.addQuoted(s);
  3827. }
  3828. else if (expr->queryName())
  3829. {
  3830. StringBuffer s;
  3831. s.append("// ").append(expr->queryName());
  3832. ctx.addQuoted(s);
  3833. }
  3834. }
  3835. typemod_t modifier = (&ctx != &declareCtx) ? typemod_member : typemod_none;
  3836. OwnedITypeInfo type = makeModifier(expr->getType(), modifier);
  3837. BuildCtx subctx(ctx);
  3838. switch (type->getTypeCode())
  3839. {
  3840. case type_row:
  3841. {
  3842. Owned<BoundRow> tempRow = declareTempRow(declareCtx, subctx, expr);
  3843. IHqlStmt * stmt = subctx.addGroup();
  3844. stmt->setIncomplete(true);
  3845. Owned<BoundRow> rowBuilder = createRowBuilder(subctx, tempRow);
  3846. Owned<IReferenceSelector> createdRef = createReferenceSelector(rowBuilder);
  3847. buildRowAssign(subctx, createdRef, expr);
  3848. finalizeTempRow(subctx, tempRow, rowBuilder);
  3849. stmt->setIncomplete(false);
  3850. stmt->mergeScopeWithContainer();
  3851. tempTarget.expr.set(tempRow->queryBound());
  3852. ctx.associate(*tempRow);
  3853. break;
  3854. }
  3855. break;
  3856. case type_table:
  3857. case type_groupedtable:
  3858. {
  3859. createTempFor(declareCtx, type, tempTarget, modifier, format);
  3860. IHqlStmt * stmt = subctx.addGroup();
  3861. stmt->setIncomplete(true);
  3862. buildDatasetAssign(subctx, tempTarget, expr);
  3863. stmt->setIncomplete(false);
  3864. stmt->mergeScopeWithContainer();
  3865. break;
  3866. }
  3867. default:
  3868. {
  3869. createTempFor(declareCtx, type, tempTarget, modifier, format);
  3870. if (ignoreSetAll)
  3871. tempTarget.isAll.clear();
  3872. IHqlStmt * stmt = subctx.addGroup();
  3873. stmt->setIncomplete(true);
  3874. buildExprAssign(subctx, tempTarget, expr);
  3875. stmt->setIncomplete(false);
  3876. stmt->mergeScopeWithContainer();
  3877. break;
  3878. }
  3879. }
  3880. }
  3881. void HqlCppTranslator::buildTempExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt, ExpressionFormat format)
  3882. {
  3883. node_operator op = expr->getOperator();
  3884. if (op == no_alias)
  3885. {
  3886. doBuildExprAlias(ctx, expr, &tgt);
  3887. return;
  3888. }
  3889. if (isCast(expr))
  3890. {
  3891. ITypeInfo * exprType = expr->queryType();
  3892. if (exprType->getStringLen() == UNKNOWN_LENGTH)
  3893. {
  3894. unsigned bestLen = getBestLengthEstimate(expr);
  3895. if (bestLen != UNKNOWN_LENGTH)
  3896. {
  3897. IHqlExpression * uncast = expr->queryChild(0);
  3898. Owned<ITypeInfo> stretchedType = getStretchedType(bestLen, exprType);
  3899. OwnedHqlExpr castExpr = ensureExprType(uncast, stretchedType);
  3900. buildTempExpr(ctx, castExpr, tgt, format);
  3901. ctx.associateExpr(expr, tgt);
  3902. return;
  3903. }
  3904. }
  3905. }
  3906. BuildCtx bestctx(ctx);
  3907. if (expr->isPure() && ctx.getMatchExpr(expr, tgt))
  3908. return;
  3909. switch (expr->getOperator())
  3910. {
  3911. case no_variable:
  3912. tgt.expr.set(expr);
  3913. return;
  3914. case no_translated:
  3915. {
  3916. if (!expr->queryChild(1))
  3917. {
  3918. IHqlExpression * value = expr->queryChild(0);
  3919. if (value->getOperator() == no_variable)
  3920. {
  3921. tgt.expr.set(value);
  3922. return;
  3923. }
  3924. }
  3925. break;
  3926. }
  3927. case no_id2blob:
  3928. buildExpr(ctx, expr, tgt);
  3929. return;
  3930. case no_externalcall:
  3931. if (format == FormatNatural && expr->isDataset())
  3932. format = hasLinkCountedModifier(expr->queryType()) ? FormatLinkedDataset : FormatBlockedDataset;
  3933. break;
  3934. }
  3935. LoopInvariantHelper helper;
  3936. if (options.optimizeLoopInvariant)
  3937. helper.getBestContext(bestctx, expr);
  3938. bool canBeAll = canSetBeAll(expr);
  3939. CHqlBoundTarget tempTarget;
  3940. buildTempExpr(bestctx, bestctx, tempTarget, expr, format, !canBeAll);
  3941. tgt.setFromTarget(tempTarget);
  3942. bestctx.associateExpr(expr, tgt);
  3943. }
  3944. void HqlCppTranslator::buildExprViaTypedTemp(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt, ITypeInfo * type)
  3945. {
  3946. OwnedHqlExpr cast = createValue(no_implicitcast, LINK(type), LINK(expr));
  3947. if (cast->isPure() && ctx.getMatchExpr(cast, tgt))
  3948. return;
  3949. LoopInvariantHelper helper;
  3950. BuildCtx bestctx(ctx);
  3951. if (options.optimizeLoopInvariant)
  3952. helper.getBestContext(bestctx, expr);
  3953. CHqlBoundTarget tempTarget;
  3954. createTempFor(bestctx, type, tempTarget, typemod_none, FormatNatural);
  3955. buildExprAssign(bestctx, tempTarget, expr);
  3956. tgt.setFromTarget(tempTarget);
  3957. if (cast->isPure())
  3958. bestctx.associateExpr(cast, tgt);
  3959. }
  3960. void HqlCppTranslator::buildExprEnsureType(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt, ITypeInfo * type)
  3961. {
  3962. if (queryUnqualifiedType(expr->queryType()) != queryUnqualifiedType(type))
  3963. buildExprViaTypedTemp(ctx, expr, tgt, type);
  3964. else
  3965. buildExpr(ctx, expr, tgt);
  3966. }
  3967. AliasKind HqlCppTranslator::doBuildAliasValue(BuildCtx & ctx, IHqlExpression * value, CHqlBoundExpr & tgt)
  3968. {
  3969. //can happen when this is called for non no_alias arguments
  3970. if (value->getOperator() == no_alias)
  3971. value = value->queryChild(0);
  3972. EvalContext * instance = queryEvalContext(ctx);
  3973. if (instance)
  3974. return instance->evaluateExpression(ctx, value, tgt, true);
  3975. expandAliases(ctx, value);
  3976. buildTempExpr(ctx, value, tgt);
  3977. return RuntimeAlias;
  3978. }
  3979. void HqlCppTranslator::doBuildExprAlias(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr * tgt)
  3980. {
  3981. //MORE These will be declared in a different context later.
  3982. IHqlExpression * value = expr->queryChild(0);
  3983. assertex(value->getOperator() != no_alias);
  3984. //The second half of this test could cause aliases to be duplicated, but has the significant effect of reducing the amount of data that is serialised.
  3985. //so far on my examples it does the latter, but doesn't seem to cause the former
  3986. if (expr->hasProperty(localAtom) || (insideOnCreate(ctx) && !expr->hasProperty(globalAtom)))
  3987. {
  3988. expandAliases(ctx, value);
  3989. if (tgt)
  3990. buildTempExpr(ctx, value, *tgt);
  3991. else
  3992. {
  3993. CHqlBoundExpr bound;
  3994. buildTempExpr(ctx, value, bound);
  3995. }
  3996. }
  3997. else
  3998. {
  3999. if (tgt)
  4000. doBuildAliasValue(ctx, value, *tgt);
  4001. else
  4002. {
  4003. CHqlBoundExpr bound;
  4004. doBuildAliasValue(ctx, value, bound);
  4005. }
  4006. }
  4007. }
  4008. void HqlCppTranslator::doBuildBoolAssign(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4009. {
  4010. if (requiresTemp(ctx, expr, true))
  4011. {
  4012. BuildCtx subctx(ctx);
  4013. assignBound(subctx, target, queryBoolExpr(false));
  4014. buildFilter(subctx, expr);
  4015. assignBound(subctx, target, queryBoolExpr(true));
  4016. }
  4017. else
  4018. {
  4019. CHqlBoundExpr temp;
  4020. buildCachedExpr(ctx, expr, temp);
  4021. assign(ctx, target, temp);
  4022. }
  4023. }
  4024. void HqlCppTranslator::doBuildExprAssign(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4025. {
  4026. CHqlBoundExpr temp;
  4027. buildExpr(ctx, expr, temp);
  4028. assign(ctx, target, temp);
  4029. }
  4030. void HqlCppTranslator::ensureSimpleExpr(BuildCtx & ctx, CHqlBoundExpr & tgt)
  4031. {
  4032. if (!isSimpleTranslatedExpr(tgt.expr))
  4033. {
  4034. OwnedHqlExpr bound = tgt.getTranslatedExpr();
  4035. buildTempExpr(ctx, bound, tgt);
  4036. }
  4037. }
  4038. IHqlExpression * HqlCppTranslator::ensureSimpleTranslatedExpr(BuildCtx & ctx, IHqlExpression * expr)
  4039. {
  4040. if (isSimpleTranslatedExpr(expr))
  4041. return LINK(expr);
  4042. OwnedHqlExpr translated = createTranslated(expr);
  4043. CHqlBoundExpr bound;
  4044. buildTempExpr(ctx, translated, bound);
  4045. return LINK(bound.expr);
  4046. }
  4047. void HqlCppTranslator::ensureHasAddress(BuildCtx & ctx, CHqlBoundExpr & tgt)
  4048. {
  4049. IHqlExpression * expr = tgt.expr;
  4050. node_operator op = expr->getOperator();
  4051. switch (op)
  4052. {
  4053. case no_deref:
  4054. case no_variable:
  4055. break;
  4056. default:
  4057. if (!isTypePassedByAddress(expr->queryType()))
  4058. {
  4059. OwnedHqlExpr bound = tgt.getTranslatedExpr();
  4060. buildTempExpr(ctx, bound, tgt);
  4061. }
  4062. break;
  4063. }
  4064. }
  4065. //---------------------------------------------------------------------------
  4066. bool optimizeVarStringCompare(node_operator op, const CHqlBoundExpr & lhs, const CHqlBoundExpr & rhs, CHqlBoundExpr & tgt)
  4067. {
  4068. IHqlExpression * rhsExpr = rhs.expr;
  4069. if ((rhsExpr->getOperator() == no_constant) && (rhsExpr->queryType()->getStringLen() == 0))
  4070. {
  4071. if ((op == no_eq) || (op == no_ne))
  4072. {
  4073. tgt.expr.setown(createValue(op, LINK(boolType), createValue(no_deref, makeCharType(), lhs.expr.getLink()), getZero()));
  4074. return true;
  4075. }
  4076. }
  4077. return false;
  4078. }
  4079. void HqlCppTranslator::doBuildExprSetCompareAll(BuildCtx & ctx, IHqlExpression * set, CHqlBoundExpr & tgt, bool invert)
  4080. {
  4081. Owned<IHqlCppSetCursor> cursor = createSetSelector(ctx, set);
  4082. cursor->buildIsAll(ctx, tgt);
  4083. if (invert)
  4084. tgt.expr.setown(getInverse(tgt.expr));
  4085. }
  4086. void HqlCppTranslator::doBuildExprSetCompareNone(BuildCtx & ctx, IHqlExpression * set, CHqlBoundExpr & tgt, bool invert)
  4087. {
  4088. Owned<IHqlCppSetCursor> cursor = createSetSelector(ctx, set);
  4089. cursor->buildExists(ctx, tgt);
  4090. if (!invert)
  4091. tgt.expr.setown(getInverse(tgt.expr));
  4092. }
  4093. bool HqlCppTranslator::doBuildExprSetCompare(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4094. {
  4095. //Special case comparison against all and null set. All other work goes through a the order code.
  4096. node_operator exprOp = expr->getOperator();
  4097. if ((exprOp == no_eq) || (exprOp == no_ne))
  4098. {
  4099. OwnedHqlExpr left = normalizeListCasts(expr->queryChild(0));
  4100. OwnedHqlExpr right = normalizeListCasts(expr->queryChild(1));
  4101. if (right->getOperator() == no_all)
  4102. doBuildExprSetCompareAll(ctx, left, tgt, exprOp==no_ne);
  4103. else if (left->getOperator() == no_all)
  4104. doBuildExprSetCompareAll(ctx, right, tgt, exprOp==no_ne);
  4105. else if (isNullList(right))
  4106. doBuildExprSetCompareNone(ctx, left, tgt, exprOp==no_ne);
  4107. else if (isNullList(left))
  4108. doBuildExprSetCompareNone(ctx, right, tgt, exprOp==no_ne);
  4109. else
  4110. return false;
  4111. return true;
  4112. }
  4113. return false;
  4114. }
  4115. IHqlExpression * HqlCppTranslator::convertBoundStringToChar(const CHqlBoundExpr & bound)
  4116. {
  4117. OwnedHqlExpr element = getElementPointer(bound.expr);
  4118. Owned<ITypeInfo> charType = makeCharType(true);
  4119. switch (element->getOperator())
  4120. {
  4121. case no_constant:
  4122. {
  4123. IValue * value = element->queryValue();
  4124. return createConstant(value->castTo(charType));
  4125. }
  4126. case no_address:
  4127. return LINK(element->queryChild(0));
  4128. }
  4129. return createValue(no_deref, charType.getClear(), element.getClear());
  4130. }
  4131. void HqlCppTranslator::doBuildExprCompare(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4132. {
  4133. IHqlExpression * left = expr->queryChild(0);
  4134. IHqlExpression * right = expr->queryChild(1);
  4135. ITypeInfo * leftType = left->queryType()->queryPromotedType();
  4136. ITypeInfo * rightType = right->queryType()->queryPromotedType();
  4137. assertex(areTypesComparable(leftType,rightType));
  4138. OwnedHqlExpr orderExpr;
  4139. CHqlBoundExpr lhs, rhs;
  4140. node_operator compareOp = expr->getOperator();
  4141. type_t tc = leftType->getTypeCode();
  4142. switch (tc)
  4143. {
  4144. case type_string:
  4145. case type_data:
  4146. case type_qstring:
  4147. {
  4148. OwnedHqlExpr simpleLeft = getSimplifyCompareArg(left);
  4149. OwnedHqlExpr simpleRight = getSimplifyCompareArg(right);
  4150. HqlExprArray args;
  4151. buildCachedExpr(ctx, simpleLeft, lhs);
  4152. buildCachedExpr(ctx, simpleRight, rhs);
  4153. //update types - lengths may be constant by now..
  4154. leftType = lhs.queryType();
  4155. rightType = rhs.queryType();
  4156. _ATOM func = queryStrCompareFunc(leftType);
  4157. //MORE: Move blank string compare here?
  4158. if (lhs.length || rhs.length || needVarStringCompare(leftType, rightType))
  4159. {
  4160. args.append(*getBoundLength(lhs));
  4161. args.append(*getElementPointer(lhs.expr));
  4162. if (func == compareStrStrAtom && isBlankString(rhs.expr))
  4163. {
  4164. func = compareStrBlankAtom;
  4165. }
  4166. else
  4167. {
  4168. args.append(*getBoundLength(rhs));
  4169. args.append(*getElementPointer(rhs.expr));
  4170. }
  4171. orderExpr.setown(bindTranslatedFunctionCall(func, args));
  4172. }
  4173. else if (options.optimizeString1Compare &&
  4174. (tc == type_string || tc == type_data) && (leftType->getSize() == 1) &&
  4175. ((compareOp == no_eq) || (compareOp == no_ne)))
  4176. {
  4177. //Optimize equality/non equality of a single character string.
  4178. //Not done for > etc because of potential issues with signed/unsigned chars
  4179. args.append(*convertBoundStringToChar(lhs));
  4180. args.append(*convertBoundStringToChar(rhs));
  4181. tgt.expr.setown(createValue(compareOp, makeBoolType(), args));
  4182. return;
  4183. }
  4184. else
  4185. {
  4186. args.append(*getElementPointer(lhs.expr));
  4187. args.append(*getElementPointer(rhs.expr));
  4188. args.append(*getSizetConstant(leftType->getSize()));
  4189. orderExpr.setown(bindTranslatedFunctionCall(memcmpAtom, args));
  4190. }
  4191. break;
  4192. }
  4193. case type_unicode:
  4194. {
  4195. OwnedHqlExpr simpleLeft = LINK(left);//getSimplifyCompareArg(left);
  4196. OwnedHqlExpr simpleRight = LINK(right);//getSimplifyCompareArg(right);
  4197. HqlExprArray args;
  4198. buildCachedExpr(ctx, simpleLeft, lhs);
  4199. buildCachedExpr(ctx, simpleRight, rhs);
  4200. assertex(haveCommonLocale(leftType, rightType));
  4201. char const * locale = getCommonLocale(leftType, rightType)->str();
  4202. args.append(*getBoundLength(lhs));
  4203. args.append(*getElementPointer(lhs.expr));
  4204. args.append(*getBoundLength(rhs));
  4205. args.append(*getElementPointer(rhs.expr));
  4206. args.append(*createConstant(locale));
  4207. orderExpr.setown(bindTranslatedFunctionCall(compareUnicodeUnicodeAtom, args));
  4208. break;
  4209. }
  4210. case type_varunicode:
  4211. {
  4212. HqlExprArray args;
  4213. buildCachedExpr(ctx, left, lhs);
  4214. buildCachedExpr(ctx, right, rhs);
  4215. assertex(haveCommonLocale(leftType, rightType));
  4216. char const * locale = getCommonLocale(leftType, rightType)->str();
  4217. args.append(*getElementPointer(lhs.expr));
  4218. args.append(*getElementPointer(rhs.expr));
  4219. args.append(*createConstant(locale));
  4220. orderExpr.setown(bindTranslatedFunctionCall(compareVUnicodeVUnicodeAtom, args));
  4221. break;
  4222. }
  4223. case type_utf8:
  4224. {
  4225. OwnedHqlExpr simpleLeft = LINK(left);//getSimplifyCompareArg(left);
  4226. OwnedHqlExpr simpleRight = LINK(right);//getSimplifyCompareArg(right);
  4227. HqlExprArray args;
  4228. buildCachedExpr(ctx, simpleLeft, lhs);
  4229. buildCachedExpr(ctx, simpleRight, rhs);
  4230. assertex(haveCommonLocale(leftType, rightType));
  4231. char const * locale = getCommonLocale(leftType, rightType)->str();
  4232. args.append(*getBoundLength(lhs));
  4233. args.append(*getElementPointer(lhs.expr));
  4234. args.append(*getBoundLength(rhs));
  4235. args.append(*getElementPointer(rhs.expr));
  4236. args.append(*createConstant(locale));
  4237. orderExpr.setown(bindTranslatedFunctionCall(compareUtf8Utf8Atom, args));
  4238. break;
  4239. }
  4240. case type_varstring:
  4241. {
  4242. HqlExprArray args;
  4243. buildCachedExpr(ctx, left, lhs);
  4244. buildCachedExpr(ctx, right, rhs);
  4245. //optimize comparison against null string.
  4246. if (optimizeVarStringCompare(compareOp, lhs, rhs, tgt) || optimizeVarStringCompare(compareOp, rhs, lhs, tgt))
  4247. return;
  4248. args.append(*getElementPointer(lhs.expr));
  4249. args.append(*getElementPointer(rhs.expr));
  4250. orderExpr.setown(bindTranslatedFunctionCall(compareVStrVStrAtom, args));
  4251. break;
  4252. }
  4253. case type_decimal:
  4254. {
  4255. HqlExprArray args;
  4256. buildCachedExpr(ctx, left, lhs);
  4257. buildCachedExpr(ctx, right, rhs);
  4258. if (!isPushed(lhs) && !isPushed(rhs) && isSameBasicType(lhs.queryType(), rhs.queryType()))
  4259. {
  4260. args.append(*getSizetConstant(leftType->getSize()));
  4261. args.append(*getPointer(lhs.expr));
  4262. args.append(*getPointer(rhs.expr));
  4263. orderExpr.setown(bindTranslatedFunctionCall(leftType->isSigned() ? DecCompareDecimalAtom : DecCompareUDecimalAtom, args));
  4264. }
  4265. else
  4266. {
  4267. bool pushedLhs = ensurePushed(ctx, lhs);
  4268. bool pushedRhs = ensurePushed(ctx, rhs);
  4269. //NB: Arguments could be pushed in opposite order 1 <=> x *2
  4270. if (pushedLhs && !pushedRhs)
  4271. orderExpr.setown(bindTranslatedFunctionCall(DecDistinctRAtom, args));
  4272. else
  4273. orderExpr.setown(bindTranslatedFunctionCall(DecDistinctAtom, args));
  4274. }
  4275. break;
  4276. }
  4277. case type_set:
  4278. case type_array:
  4279. {
  4280. if (doBuildExprSetCompare(ctx, expr, tgt))
  4281. return;
  4282. //fallthrough....
  4283. }
  4284. case type_table:
  4285. case type_groupedtable:
  4286. case type_row:
  4287. case type_record:
  4288. {
  4289. IHqlExpression * orderExpr = createValue(no_order, LINK(signedType), LINK(left), LINK(right));
  4290. OwnedHqlExpr cmpExpr = createBoolExpr(compareOp, orderExpr, createConstant(signedType->castFrom(true, 0)));
  4291. buildExpr(ctx, cmpExpr, tgt);
  4292. return;
  4293. }
  4294. case type_swapint:
  4295. case type_packedint:
  4296. {
  4297. Owned<ITypeInfo> type = makeIntType(leftType->getSize(), leftType->isSigned());
  4298. IHqlExpression * intLeft = createValue(no_implicitcast, type.getLink(), LINK(left));
  4299. IHqlExpression * intRight = createValue(no_implicitcast, type.getLink(), LINK(right));
  4300. OwnedHqlExpr transformed = createValue(compareOp, makeBoolType(), intLeft, intRight);
  4301. doBuildPureSubExpr(ctx, transformed, tgt);
  4302. return;
  4303. }
  4304. default:
  4305. doBuildPureSubExpr(ctx, expr, tgt);
  4306. return;
  4307. }
  4308. tgt.expr.setown(createValue(compareOp, LINK(boolType), LINK(orderExpr), createConstant(orderExpr->queryType()->castFrom(true, 0))));
  4309. }
  4310. //---------------------------------------------------------------------------
  4311. //-- no_and --
  4312. void HqlCppTranslator::doBuildFilterToTarget(BuildCtx & ctx, const CHqlBoundTarget & isOk, HqlExprArray & conds, bool invert)
  4313. {
  4314. LinkedHqlExpr test = isOk.expr;
  4315. if (invert)
  4316. test.setown(createValue(no_not, makeBoolType(), LINK(test)));
  4317. unsigned max = conds.ordinality();
  4318. unsigned curIndex = 0;
  4319. for (unsigned outer =0; curIndex < max; outer += MAX_NESTED_CASES)
  4320. {
  4321. BuildCtx subctx(ctx);
  4322. if (outer != 0)
  4323. subctx.addFilter(test);
  4324. buildExprAssign(subctx, isOk, queryBoolExpr(invert)); // if(!invert,false,true) => invert
  4325. doBuildFilterNextAndRange(subctx, curIndex, MAX_NESTED_CASES, conds);
  4326. buildExprAssign(subctx, isOk, queryBoolExpr(!invert)); // if(!invert,true,false) => !invert
  4327. }
  4328. }
  4329. void HqlCppTranslator::doBuildFilterAnd(BuildCtx & ctx, IHqlExpression * expr)
  4330. {
  4331. HqlExprArray conds;
  4332. expr->unwindList(conds, no_and);
  4333. //Estimate the depth generated by the conditions - it may be wrong because
  4334. //aliases generated in outer levels can stop temporaries being required later.
  4335. unsigned numConds = conds.ordinality();
  4336. unsigned depthEstimate = 1;
  4337. for (unsigned i=1; i < numConds; i++)
  4338. if (requiresTemp(ctx, &conds.item(i), true))
  4339. depthEstimate++;
  4340. if (depthEstimate < MAX_NESTED_CASES)
  4341. {
  4342. unsigned curIndex = 0;
  4343. doBuildFilterNextAndRange(ctx, curIndex, numConds, conds);
  4344. }
  4345. else
  4346. {
  4347. CHqlBoundTarget isOk;
  4348. createTempFor(ctx, expr, isOk);
  4349. doBuildFilterToTarget(ctx, isOk, conds, false);
  4350. ctx.addFilter(isOk.expr);
  4351. }
  4352. }
  4353. void HqlCppTranslator::doBuildFilterNextAndRange(BuildCtx & ctx, unsigned & curIndex, unsigned maxIterations, HqlExprArray & conds)
  4354. {
  4355. unsigned max = conds.ordinality();
  4356. for (unsigned i=0; (i < maxIterations) && (curIndex != max); i++)
  4357. {
  4358. unsigned last;
  4359. expandAliases(ctx, &conds.item(curIndex));
  4360. for (last = curIndex+1; last < max; last++)
  4361. if (requiresTemp(ctx, &conds.item(last), true))
  4362. break;
  4363. doBuildFilterAndRange(ctx, curIndex, last, conds);
  4364. curIndex = last;
  4365. }
  4366. }
  4367. void HqlCppTranslator::doBuildFilterAndRange(BuildCtx & ctx, unsigned first, unsigned last, HqlExprArray & conds)
  4368. {
  4369. if (first+1 == last)
  4370. buildFilter(ctx, &conds.item(first));
  4371. else
  4372. {
  4373. HqlExprArray args;
  4374. for (unsigned k = first; k < last; k++)
  4375. args.append(OLINK(conds.item(k)));
  4376. OwnedHqlExpr test = createValue(no_and, makeBoolType(), args);
  4377. buildFilterViaExpr(ctx, test);
  4378. }
  4379. }
  4380. void HqlCppTranslator::doBuildAssignAnd(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr, bool invert)
  4381. {
  4382. HqlExprArray conds;
  4383. expr->unwindList(conds, no_and);
  4384. doBuildFilterToTarget(ctx, target, conds, invert);
  4385. }
  4386. void HqlCppTranslator::doBuildAssignOr(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4387. {
  4388. BuildCtx subctx(ctx);
  4389. HqlExprArray conds;
  4390. expr->unwindList(conds, no_or);
  4391. unsigned first = 0;
  4392. unsigned max = conds.ordinality();
  4393. while (first < max)
  4394. {
  4395. unsigned last = first+1;
  4396. //special case no_in because it always creates a temporary, so may as well assign on its own
  4397. if (conds.item(first).getOperator() != no_in)
  4398. {
  4399. for (; last < max; last++)
  4400. {
  4401. IHqlExpression & cur = conds.item(last);
  4402. if ((cur.getOperator() == no_in) || requiresTemp(subctx, &cur, true))
  4403. break;
  4404. }
  4405. }
  4406. if (first != 0 || last != max)
  4407. {
  4408. if (last != first+1)
  4409. {
  4410. OwnedHqlExpr left = createBalanced(no_or, queryBoolType(), conds, first, last);
  4411. doBuildExprAssign(subctx, target, left);
  4412. }
  4413. else
  4414. buildExprAssign(subctx, target, &conds.item(first));
  4415. if (last != max)
  4416. {
  4417. OwnedHqlExpr inverse = getInverse(target.expr);
  4418. subctx.addFilter(inverse);
  4419. }
  4420. }
  4421. else
  4422. {
  4423. doBuildExprAssign(subctx, target, expr);
  4424. }
  4425. first = last;
  4426. }
  4427. }
  4428. //---------------------------------------------------------------------------
  4429. //-- no_case --
  4430. void HqlCppTranslator::doBuildCaseInfo(IHqlExpression * expr, HqlCppCaseInfo & info)
  4431. {
  4432. unsigned maxMaps = expr->numChildren()-1;
  4433. unsigned index = 0;
  4434. if (expr->getOperator() == no_case)
  4435. {
  4436. info.setCond(expr->queryChild(0));
  4437. index++;
  4438. }
  4439. for (;index<maxMaps;index++)
  4440. info.addPair(expr->queryChild(index));
  4441. info.setDefault(expr->queryChild(maxMaps));
  4442. }
  4443. void HqlCppTranslator::doBuildInCaseInfo(IHqlExpression * expr, HqlCppCaseInfo & info, IHqlExpression * normalized)
  4444. {
  4445. bool valueIfMatch = (expr->getOperator() == no_in);
  4446. HqlExprArray args;
  4447. LinkedHqlExpr values = normalized;
  4448. if (!normalized)
  4449. values.setown(normalizeListCasts(expr->queryChild(1)));
  4450. info.setCond(expr->queryChild(0));
  4451. cvtInListToPairs(args, values, valueIfMatch);
  4452. info.addPairs(args);
  4453. info.setDefault(queryBoolExpr(!valueIfMatch));
  4454. }
  4455. void HqlCppTranslator::doBuildAssignInStored(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4456. {
  4457. OwnedHqlExpr values = normalizeListCasts(expr->queryChild(1));
  4458. CHqlBoundExpr bound;
  4459. if (values->isPure())
  4460. ctx.getMatchExpr(values, bound);
  4461. if (options.optimizeLoopInvariant && !bound.expr)
  4462. {
  4463. if (values->getOperator() == no_createset)
  4464. {
  4465. IHqlExpression * ds = values->queryChild(0);
  4466. //MORE: This is a special case - it should check if the dataset can be iterated without any projection
  4467. switch (ds->getOperator())
  4468. {
  4469. case no_select:
  4470. case no_rows:
  4471. break;
  4472. default:
  4473. {
  4474. //Evaluate the dataset into a temporary - the iterator will match it up later
  4475. //Evaluating the dataset instead of the set since this is likely to avoid a memcpy with link counted rows enabled.
  4476. LoopInvariantHelper helper;
  4477. BuildCtx bestctx(ctx);
  4478. if (helper.getBestContext(bestctx, ds))
  4479. {
  4480. CHqlBoundExpr temp;
  4481. buildTempExpr(ctx, ds, temp);
  4482. }
  4483. break;
  4484. }
  4485. }
  4486. }
  4487. else
  4488. {
  4489. LoopInvariantHelper helper;
  4490. BuildCtx bestctx(ctx);
  4491. if (helper.getBestContext(bestctx, values))
  4492. {
  4493. //Unfortunately this will do strength reduction again, but shouldn't take too long.
  4494. buildTempExpr(bestctx, values, bound);
  4495. }
  4496. }
  4497. }
  4498. if (bound.expr)
  4499. values.setown(bound.getTranslatedExpr());
  4500. bool valueIfMatch = (expr->getOperator() == no_in);
  4501. ITypeInfo * elementType = values->queryType()->queryChildType();
  4502. Owned<ITypeInfo> compareType = getPromotedECLCompareType(expr->queryChild(0)->queryType(), elementType);
  4503. CHqlBoundExpr boundSearch;
  4504. OwnedHqlExpr castSearch = ensureExprType(expr->queryChild(0), compareType);
  4505. BuildCtx subctx(ctx);
  4506. Owned<IHqlCppSetCursor> cursor = createSetSelector(ctx, values);
  4507. CHqlBoundExpr isAll;
  4508. cursor->buildIsAll(ctx, isAll);
  4509. if (isAll.expr->queryValue())
  4510. {
  4511. if (isAll.expr->queryValue()->getBoolValue())
  4512. {
  4513. buildExprAssign(subctx, target, queryBoolExpr(valueIfMatch));
  4514. //If this inverted the test we would need to do more.
  4515. return;
  4516. }
  4517. }
  4518. else
  4519. {
  4520. IHqlStmt * stmt = subctx.addFilter(isAll.expr);
  4521. buildExprAssign(subctx, target, queryBoolExpr(valueIfMatch));
  4522. subctx.selectElse(stmt);
  4523. }
  4524. //result = false/true
  4525. buildSimpleExpr(subctx, castSearch, boundSearch);
  4526. buildExprAssign(subctx, target, queryBoolExpr(!valueIfMatch));
  4527. //iterate through the set
  4528. bool needToBreak = !cursor->isSingleValued();
  4529. CHqlBoundExpr boundCurElement;
  4530. cursor->buildIterateLoop(subctx, boundCurElement, needToBreak);
  4531. OwnedHqlExpr curElement = boundCurElement.getTranslatedExpr();
  4532. OwnedHqlExpr castCurElement = ensureExprType(curElement, compareType);
  4533. //if match then
  4534. OwnedHqlExpr matchTest = createValue(no_eq, makeBoolType(), boundSearch.getTranslatedExpr(), LINK(castCurElement));
  4535. buildFilter(subctx, matchTest);
  4536. //result = true/false + break loop.
  4537. buildExprAssign(subctx, target, queryBoolExpr(valueIfMatch));
  4538. if (needToBreak)
  4539. subctx.addBreak();
  4540. }
  4541. void HqlCppTranslator::doBuildAssignInCreateSet(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4542. {
  4543. IHqlExpression * setExpr = expr->queryChild(1);
  4544. IHqlExpression * dataset = setExpr->queryChild(0);
  4545. IHqlExpression * selected = setExpr->queryChild(1);
  4546. bool valueIfMatch = (expr->getOperator() == no_in);
  4547. ITypeInfo * elementType = setExpr->queryType()->queryChildType();
  4548. Owned<ITypeInfo> compareType = getPromotedECLCompareType(expr->queryChild(0)->queryType(), elementType);
  4549. CHqlBoundExpr boundSearch;
  4550. OwnedHqlExpr castSearch = ensureExprType(expr->queryChild(0), compareType);
  4551. //result = false/true
  4552. buildSimpleExpr(ctx, castSearch, boundSearch);
  4553. buildExprAssign(ctx, target, queryBoolExpr(!valueIfMatch));
  4554. //iterate through the set
  4555. bool needToBreak = !hasNoMoreRowsThan(dataset, 1);
  4556. BuildCtx loopctx(ctx);
  4557. buildDatasetIterate(loopctx, dataset, needToBreak);
  4558. //if match then
  4559. OwnedHqlExpr matchTest = createValue(no_eq, makeBoolType(), boundSearch.getTranslatedExpr(), ensureExprType(selected, compareType));
  4560. buildFilter(loopctx, matchTest);
  4561. //result = true/false + break loop.
  4562. buildExprAssign(loopctx, target, queryBoolExpr(valueIfMatch));
  4563. if (needToBreak)
  4564. loopctx.addBreak();
  4565. }
  4566. void HqlCppTranslator::doBuildAssignIn(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4567. {
  4568. OwnedHqlExpr values = normalizeListCasts(expr->queryChild(1));
  4569. node_operator op = expr->getOperator();
  4570. bool valueIfMatch = (op == no_in);
  4571. switch (values->getOperator())
  4572. {
  4573. case no_all:
  4574. buildExprAssign(ctx, target, queryBoolExpr(valueIfMatch));
  4575. break;
  4576. case no_null:
  4577. buildExprAssign(ctx, target, queryBoolExpr(!valueIfMatch));
  4578. break;
  4579. case no_list:
  4580. {
  4581. HqlCppCaseInfo info(*this);
  4582. doBuildInCaseInfo(expr, info, values);
  4583. info.buildAssign(ctx, target);
  4584. break;
  4585. }
  4586. case no_createset:
  4587. {
  4588. //Look further at bug #52745.eclxml and what causes the poor code.
  4589. //if (canIterateInline(&ctx, values->queryChild(0)))
  4590. // doBuildAssignInCreateSet(ctx, target, expr);
  4591. //else
  4592. doBuildAssignInStored(ctx, target, expr);
  4593. break;
  4594. }
  4595. #if 0
  4596. //Possible optimizations, but I don't have any examples that would trigger them, so don't enable
  4597. case no_if:
  4598. {
  4599. BuildCtx subctx(ctx);
  4600. OwnedHqlExpr inLhs = createValue(expr->getOperator(), LINK(expr->queryChild(0)), LINK(values->queryChild(1)));
  4601. OwnedHqlExpr inRhs = createValue(expr->getOperator(), LINK(expr->queryChild(0)), LINK(values->queryChild(2)));
  4602. IHqlStmt * stmt = buildFilterViaExpr(subctx, values->queryChild(0));
  4603. buildExprAssign(subctx, target, inLhs);
  4604. subctx.selectElse(stmt);
  4605. buildExprAssign(subctx, target, inRhs);
  4606. break;
  4607. }
  4608. case no_addsets:
  4609. if (op == no_in)
  4610. {
  4611. BuildCtx subctx(ctx);
  4612. OwnedHqlExpr inLhs = createValue(expr->getOperator(), LINK(expr->queryChild(0)), LINK(values->queryChild(0)));
  4613. OwnedHqlExpr inRhs = createValue(expr->getOperator(), LINK(expr->queryChild(0)), LINK(values->queryChild(1)));
  4614. buildExprAssign(ctx, target, inLhs);
  4615. OwnedHqlExpr test = getInverse(target.expr);
  4616. subctx.addFilter(test);
  4617. buildExprAssign(subctx, target, inRhs);
  4618. break;
  4619. }
  4620. #endif
  4621. //fall through
  4622. default:
  4623. doBuildAssignInStored(ctx, target, expr);
  4624. break;
  4625. }
  4626. }
  4627. //---------------------------------------------------------------------------
  4628. void HqlCppTranslator::doBuildExprArith(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4629. {
  4630. ITypeInfo * type = expr->queryType();
  4631. switch (type->getTypeCode())
  4632. {
  4633. case type_decimal:
  4634. {
  4635. bindAndPush(ctx, expr->queryChild(0));
  4636. bindAndPush(ctx, expr->queryChild(1));
  4637. HqlExprArray args;
  4638. _ATOM func;
  4639. switch (expr->getOperator())
  4640. {
  4641. case no_add: func = DecAddAtom; break;
  4642. case no_div: func = DecDivideAtom; break;
  4643. case no_modulus: func = DecModulusAtom; break;
  4644. case no_mul: func = DecMulAtom; break;
  4645. case no_sub: func = DecSubAtom; break;
  4646. default: UNIMPLEMENTED;
  4647. }
  4648. callProcedure(ctx, func, args);
  4649. tgt.expr.setown(createValue(no_decimalstack, LINK(type)));
  4650. }
  4651. break;
  4652. case type_swapint:
  4653. case type_packedint:
  4654. {
  4655. //someone is being deliberately perverse....
  4656. ITypeInfo * type = expr->queryType();
  4657. ITypeInfo * intType = makeIntType(type->getSize(), type->isSigned());
  4658. IHqlExpression * lhs = expr->queryChild(0);
  4659. IHqlExpression * rhs = expr->queryChild(1);
  4660. assertex(isSameBasicType(type, lhs->queryType()));
  4661. assertex(isSameBasicType(type, rhs->queryType()));
  4662. lhs = createValue(no_implicitcast, LINK(intType), LINK(lhs));
  4663. rhs = createValue(no_implicitcast, LINK(intType), LINK(rhs));
  4664. IHqlExpression * newExpr = createValue(expr->getOperator(), intType, lhs, rhs);
  4665. OwnedHqlExpr castNewExpr = createValue(no_implicitcast, LINK(type), newExpr);
  4666. buildExpr(ctx, castNewExpr, tgt);
  4667. break;
  4668. }
  4669. default:
  4670. doBuildPureSubExpr(ctx, expr, tgt);
  4671. break;
  4672. }
  4673. }
  4674. void HqlCppTranslator::doBuildExprAdd(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4675. {
  4676. if (expr->queryType()->getTypeCode() != type_int)
  4677. {
  4678. doBuildExprArith(ctx, expr, tgt);
  4679. return;
  4680. }
  4681. CHqlBoundExpr boundL, boundR;
  4682. buildExpr(ctx, expr->queryChild(0), boundL);
  4683. bool WORK_AROUND_GCC_CONDITION_BUG = (options.targetCompiler == GccCppCompiler);
  4684. if (WORK_AROUND_GCC_CONDITION_BUG && expr->queryChild(1)->getOperator() == no_if)
  4685. buildTempExpr(ctx, expr->queryChild(1), boundR);
  4686. else
  4687. buildExpr(ctx, expr->queryChild(1), boundR);
  4688. tgt.expr.setown(adjustBoundIntegerValues(boundL.expr, boundR.expr, false));
  4689. }
  4690. //---------------------------------------------------------------------------
  4691. void HqlCppTranslator::doBuildExprNegate(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4692. {
  4693. ITypeInfo * type = expr->queryType();
  4694. switch (type->getTypeCode())
  4695. {
  4696. case type_decimal:
  4697. {
  4698. bindAndPush(ctx, expr->queryChild(0));
  4699. HqlExprArray args;
  4700. callProcedure(ctx, DecNegateAtom, args);
  4701. tgt.expr.setown(createValue(no_decimalstack, LINK(type)));
  4702. }
  4703. break;
  4704. case type_data:
  4705. case type_qstring:
  4706. case type_string:
  4707. case type_varstring:
  4708. case type_unicode:
  4709. case type_varunicode:
  4710. case type_utf8:
  4711. throwError(HQLERR_MinusOnString);
  4712. default:
  4713. doBuildPureSubExpr(ctx, expr, tgt);
  4714. break;
  4715. }
  4716. }
  4717. //---------------------------------------------------------------------------
  4718. void HqlCppTranslator::doBuildExprRound(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4719. {
  4720. IHqlExpression * arg = expr->queryChild(0);
  4721. node_operator op = expr->getOperator();
  4722. switch (arg->queryType()->getTypeCode())
  4723. {
  4724. case type_decimal:
  4725. {
  4726. bindAndPush(ctx, arg);
  4727. HqlExprArray args;
  4728. if (op == no_round)
  4729. {
  4730. IHqlExpression * places = queryRealChild(expr, 1);
  4731. if (places)
  4732. {
  4733. args.append(*LINK(places));
  4734. callProcedure(ctx, DecRoundToAtom, args);
  4735. }
  4736. else
  4737. callProcedure(ctx, DecRoundAtom, args);
  4738. }
  4739. else
  4740. callProcedure(ctx, DecRoundUpAtom, args);
  4741. assertex(expr->queryType()->getTypeCode() == type_decimal);
  4742. tgt.expr.setown(createValue(no_decimalstack, expr->getType()));
  4743. }
  4744. break;
  4745. default:
  4746. {
  4747. if (op == no_round)
  4748. {
  4749. if (queryRealChild(expr, 1))
  4750. doBuildExprSysFunc(ctx, expr, tgt, roundToAtom);
  4751. else
  4752. doBuildExprSysFunc(ctx, expr, tgt, roundAtom);
  4753. }
  4754. else
  4755. doBuildExprSysFunc(ctx, expr, tgt, roundupAtom);
  4756. break;
  4757. }
  4758. }
  4759. }
  4760. void HqlCppTranslator::doBuildExprTrunc(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4761. {
  4762. IHqlExpression * arg = expr->queryChild(0);
  4763. switch (arg->queryType()->getTypeCode())
  4764. {
  4765. case type_decimal:
  4766. {
  4767. bindAndPush(ctx, arg);
  4768. HqlExprArray args;
  4769. callProcedure(ctx, DecTruncateAtom, args);
  4770. assertex(expr->queryType()->getTypeCode() == type_decimal);
  4771. tgt.expr.setown(createValue(no_decimalstack, expr->getType()));
  4772. }
  4773. break;
  4774. default:
  4775. {
  4776. doBuildExprSysFunc(ctx, expr, tgt, truncateAtom);
  4777. break;
  4778. }
  4779. }
  4780. }
  4781. //---------------------------------------------------------------------------
  4782. void HqlCppTranslator::doBuildExprAbs(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  4783. {
  4784. ITypeInfo * type = expr->queryType();
  4785. switch (type->getTypeCode())
  4786. {
  4787. case type_decimal:
  4788. {
  4789. bindAndPush(ctx, expr->queryChild(0));
  4790. HqlExprArray args;
  4791. _ATOM func = DecAbsAtom;
  4792. callProcedure(ctx, func, args);
  4793. tgt.expr.setown(createValue(no_decimalstack, LINK(type)));
  4794. }
  4795. break;
  4796. case type_int:
  4797. case type_swapint:
  4798. case type_packedint:
  4799. case type_real:
  4800. {
  4801. CHqlBoundExpr temp;
  4802. buildTempExpr(ctx, expr->queryChild(0), temp);
  4803. ITypeInfo * type = expr->getType();
  4804. IHqlExpression * cond = createValue(no_ge, makeBoolType(), temp.expr.getLink(), createConstant(type->castFrom(true, 0)));
  4805. tgt.expr.setown(createValue(no_if, type, cond, temp.expr.getLink(), createValue(no_negate, LINK(type), temp.expr.getLink())));
  4806. }
  4807. break;
  4808. default:
  4809. buildExpr(ctx, expr->queryChild(0), tgt);
  4810. break;
  4811. }
  4812. }
  4813. //---------------------------------------------------------------------------
  4814. void HqlCppTranslator::doBuildAssignCatch(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  4815. {
  4816. BuildCtx subctx(ctx);
  4817. subctx.addGroup();
  4818. BuildCtx tryctx(subctx);
  4819. tryctx.addQuotedCompound("try");
  4820. buildExprAssign(tryctx, target, expr->queryChild(0));
  4821. BuildCtx catchctx(subctx);
  4822. catchctx.addQuotedCompound("catch (IException * e)");
  4823. IHqlExpression * exceptVar = associateLocalFailure(catchctx, "e");
  4824. buildExprAssign(catchctx, target, expr->queryChild(1));
  4825. HqlExprArray args;
  4826. args.append(*LINK(exceptVar));
  4827. callProcedure(catchctx, freeExceptionAtom, args);
  4828. }
  4829. //---------------------------------------------------------------------------
  4830. //-- no_externalcall --
  4831. IHqlExpression * getCastParameter(IHqlExpression * curParam, ITypeInfo * argType)
  4832. {
  4833. type_t atc = argType->getTypeCode();
  4834. //Remove a few unnecessary casts which clutter up the code/or make it less efficient
  4835. if (isCast(curParam) && (curParam->queryType() == argType))
  4836. {
  4837. //If the following code is incorrect, the casts should get added back by the code that follows
  4838. IHqlExpression * uncast = curParam->queryChild(0);
  4839. //casts to larger size integers
  4840. if (atc == type_int)
  4841. curParam = uncast;
  4842. else if ((atc == type_unicode) && (uncast->queryType()->getTypeCode() == type_varunicode))
  4843. curParam = uncast;
  4844. else if ((atc == type_string) && (uncast->queryType()->getTypeCode() == type_varstring))
  4845. curParam = uncast;
  4846. }
  4847. ITypeInfo * paramType = curParam->queryType();
  4848. type_t ptc = paramType->getTypeCode();
  4849. if ((atc != ptc) && !(atc == type_row && ptc == type_table))
  4850. {
  4851. switch (atc)
  4852. {
  4853. case type_unicode:
  4854. if ((argType->getSize() == UNKNOWN_LENGTH) && (ptc == type_varunicode))
  4855. return LINK(curParam);
  4856. break;
  4857. case type_string:
  4858. if ((argType->getSize() == UNKNOWN_LENGTH) &&
  4859. ((ptc == type_varstring) && (argType->queryCharset() == paramType->queryCharset())))
  4860. return LINK(curParam);
  4861. break;
  4862. case type_row:
  4863. case type_table:
  4864. case type_groupedtable:
  4865. {
  4866. IHqlExpression * record = queryRecord(argType);
  4867. if (record && (record->numChildren() != 0))
  4868. {
  4869. //really need to project instead.
  4870. //return ensureExprType(curParam, argType);
  4871. }
  4872. return LINK(curParam);
  4873. }
  4874. }
  4875. return ensureExprType(curParam, argType);
  4876. }
  4877. ITypeInfo * childType = argType->queryChildType();
  4878. if (paramType->queryTypeBase() != argType)
  4879. {
  4880. size32_t argSize = argType->getSize();
  4881. switch (atc)
  4882. {
  4883. case type_int:
  4884. case type_real:
  4885. if (argSize <= paramType->getSize())
  4886. return ensureExprType(curParam, argType);
  4887. break;
  4888. case type_decimal:
  4889. //Don't need explicit cast to cast between different sizes of these types...
  4890. //Will be done automatically by the compiler.
  4891. break;
  4892. case type_unicode:
  4893. //Don't need cast between different locales
  4894. if ((argSize != paramType->getSize()) && (argSize != UNKNOWN_LENGTH))
  4895. {
  4896. Owned<ITypeInfo> modArgType = makeUnicodeType(argType->getStringLen(), curParam->queryType()->queryLocale());
  4897. return ensureExprType(curParam, modArgType);
  4898. }
  4899. break;
  4900. case type_varunicode:
  4901. //Don't need cast between different locales
  4902. if(argSize != paramType->getSize())
  4903. {
  4904. Owned<ITypeInfo> modArgType = makeVarUnicodeType(argType->getStringLen(), curParam->queryType()->queryLocale());
  4905. return ensureExprType(curParam, modArgType);
  4906. }
  4907. break;
  4908. case type_utf8:
  4909. //Don't need cast between different locales
  4910. if(argSize != paramType->getSize())
  4911. {
  4912. Owned<ITypeInfo> modArgType = makeUtf8Type(argType->getStringLen(), curParam->queryType()->queryLocale());
  4913. return ensureExprType(curParam, modArgType);
  4914. }
  4915. break;
  4916. case type_set:
  4917. if (childType)
  4918. return ensureExprType(curParam, argType);
  4919. break;
  4920. case type_table:
  4921. case type_groupedtable:
  4922. case type_row:
  4923. {
  4924. IHqlExpression * record = queryRecord(argType);
  4925. if (record && (record->numChildren() != 0))
  4926. {
  4927. //really need to project instead.
  4928. //return ensureExprType(curParam, argType);
  4929. }
  4930. break;
  4931. }
  4932. default:
  4933. return ensureExprType(curParam, argType);
  4934. }
  4935. }
  4936. // if (argType->queryCharset() != paramType->queryCharset())
  4937. // return ensureExprType(curParam, argType);
  4938. return LINK(curParam);
  4939. }
  4940. void HqlCppTranslator::normalizeBoundExpr(BuildCtx & ctx, CHqlBoundExpr & bound)
  4941. {
  4942. bound.expr.setown(convertWrapperToPointer(bound.expr));
  4943. }
  4944. IHqlExpression * HqlCppTranslator::doBuildInternalFunction(IHqlExpression * funcdef)
  4945. {
  4946. unsigned match = internalFunctions.find(*funcdef);
  4947. if (match != NotFound)
  4948. return LINK(&internalFunctionExternals.item(match));
  4949. OwnedHqlExpr externalFuncdef = createExternalFuncdefFromInternal(funcdef);
  4950. internalFunctions.append(*LINK(funcdef));
  4951. internalFunctionExternals.append(*LINK(externalFuncdef));
  4952. buildFunctionDefinition(funcdef);
  4953. return LINK(externalFuncdef);
  4954. }
  4955. void HqlCppTranslator::doBuildCall(BuildCtx & ctx, const CHqlBoundTarget * tgt, IHqlExpression * expr, CHqlBoundExpr * result)
  4956. {
  4957. if (result && expr->isPure() && ctx.getMatchExpr(expr, *result))
  4958. return;
  4959. LinkedHqlExpr funcdef;
  4960. if (expr->getOperator() == no_externalcall)
  4961. {
  4962. funcdef.set(expr->queryExternalDefinition());
  4963. assertex(funcdef != NULL);
  4964. useFunction(funcdef);
  4965. }
  4966. else
  4967. {
  4968. IHqlExpression * def = expr->queryBody()->queryFunctionDefinition();
  4969. assertex(def);
  4970. funcdef.setown(doBuildInternalFunction(def));
  4971. }
  4972. IHqlExpression * external = funcdef->queryChild(0);
  4973. IHqlExpression * formals = funcdef->queryChild(1);
  4974. if (external->hasProperty(ctxmethodAtom))
  4975. ensureContextAvailable(ctx);
  4976. if (external->hasProperty(gctxmethodAtom) || external->hasProperty(globalContextAtom))
  4977. {
  4978. if (!ctx.queryMatchExpr(globalContextMarkerExpr))
  4979. throwError1(HQLERR_FuncNotInGlobalContext, external->queryName()->str());
  4980. }
  4981. unsigned maxArg = formals->numChildren();
  4982. unsigned maxParam = expr->numChildren();
  4983. bool returnByReference = false;
  4984. bool returnMustAssign = false;
  4985. HqlExprArray args;
  4986. unsigned arg = 0;
  4987. unsigned param;
  4988. unsigned firstParam = 0;
  4989. bool isMethod = external->hasProperty(methodAtom) || external->hasProperty(omethodAtom) ;
  4990. bool newFormatSet = !external->hasProperty(oldSetFormatAtom);
  4991. bool translateSetReturn = false;
  4992. if (isMethod)
  4993. {
  4994. CHqlBoundExpr bound;
  4995. buildExpr(ctx, expr->queryChild(firstParam++), bound);
  4996. args.append(*bound.expr.getClear());
  4997. }
  4998. if (external->hasProperty(userMatchFunctionAtom))
  4999. {
  5000. //MORE: Test valid in this location...
  5001. args.append(*createVariable("walker", makeBoolType()));
  5002. }
  5003. bool doneAssign = false;
  5004. CHqlBoundExpr localBound;
  5005. CHqlBoundTarget localTarget;
  5006. Linked<BoundRow> resultRow;
  5007. Linked<BoundRow> resultRowBuilder;
  5008. Owned<ITypeInfo> targetType = tgt ? LINK(tgt->queryType()) : makeVoidType();
  5009. ITypeInfo * retType = funcdef->queryType()->queryChildType();
  5010. BoundRow * resultSelfCursor = NULL;
  5011. switch (retType->getTypeCode())
  5012. {
  5013. case type_varstring:
  5014. case type_varunicode:
  5015. if (retType->getSize() == UNKNOWN_LENGTH)
  5016. {
  5017. if (hasConstModifier(retType))
  5018. break;
  5019. returnMustAssign = true;
  5020. if (tgt && !tgt->isFixedSize())
  5021. {
  5022. doneAssign = true;
  5023. localBound.expr.set(tgt->expr);
  5024. }
  5025. else
  5026. localBound.expr.setown(createWrapperTemp(ctx, retType, typemod_none));
  5027. break;
  5028. }
  5029. else
  5030. {
  5031. //fixed size strings => just pass pointer
  5032. IHqlExpression * resultVar = ctx.getTempDeclare(retType, NULL);
  5033. args.append(*getElementPointer(resultVar));
  5034. localBound.expr.setown(resultVar);
  5035. }
  5036. returnByReference = true;
  5037. break;
  5038. case type_string:
  5039. case type_data:
  5040. case type_qstring:
  5041. case type_unicode:
  5042. case type_utf8:
  5043. if (retType->getSize() == UNKNOWN_LENGTH)
  5044. {
  5045. OwnedHqlExpr lenVar;
  5046. OwnedHqlExpr strVar;
  5047. if (tgt && !tgt->isFixedSize())
  5048. {
  5049. doneAssign = true;
  5050. strVar.set(tgt->expr);
  5051. lenVar.set(tgt->length);
  5052. }
  5053. else
  5054. {
  5055. strVar.setown(createWrapperTemp(ctx, retType, typemod_none));
  5056. lenVar.setown(ctx.getTempDeclare(sizetType, NULL));
  5057. }
  5058. args.append(*LINK(lenVar));
  5059. args.append(*createValue(no_reference, strVar->getType(), LINK(strVar)));
  5060. localBound.length.set(lenVar);
  5061. localBound.expr.set(strVar);
  5062. }
  5063. else
  5064. {
  5065. //fixed size strings => just pass pointer
  5066. if (tgt && tgt->isFixedSize() && targetType->queryPromotedType() == retType)
  5067. {
  5068. doneAssign = true;
  5069. args.append(*getElementPointer(tgt->expr));
  5070. localBound.expr.set(tgt->expr);
  5071. }
  5072. else
  5073. {
  5074. IHqlExpression * resultVar = ctx.getTempDeclare(retType, NULL);
  5075. args.append(*getElementPointer(resultVar));
  5076. localBound.expr.setown(resultVar);
  5077. }
  5078. }
  5079. returnByReference = true;
  5080. break;
  5081. case type_set:
  5082. {
  5083. translateSetReturn = !newFormatSet;
  5084. OwnedHqlExpr lenVar;
  5085. OwnedHqlExpr strVar;
  5086. OwnedHqlExpr isAll;
  5087. if (tgt && !tgt->isFixedSize())
  5088. {
  5089. doneAssign = true;
  5090. strVar.set(tgt->expr);
  5091. if (translateSetReturn)
  5092. lenVar.setown(ctx.getTempDeclare(unsignedType, NULL));
  5093. else
  5094. lenVar.set(tgt->length);
  5095. assertex(tgt->isAll != NULL);
  5096. isAll.set(tgt->isAll);
  5097. }
  5098. else
  5099. {
  5100. Owned<ITypeInfo> dataType = makeDataType(UNKNOWN_LENGTH);
  5101. strVar.setown(createWrapperTemp(ctx, dataType, typemod_none));
  5102. if (translateSetReturn)
  5103. {
  5104. lenVar.setown(ctx.getTempDeclare(unsignedType, NULL));
  5105. }
  5106. else
  5107. {
  5108. lenVar.setown(ctx.getTempDeclare(sizetType, NULL));
  5109. isAll.setown(ctx.getTempDeclare(boolType, NULL));
  5110. }
  5111. }
  5112. if (newFormatSet)
  5113. args.append(*LINK(isAll));
  5114. args.append(*LINK(lenVar));
  5115. args.append(*createValue(no_reference, strVar->getType(), LINK(strVar)));
  5116. if (newFormatSet)
  5117. {
  5118. localBound.length.set(lenVar);
  5119. }
  5120. else
  5121. {
  5122. localBound.count.set(lenVar);
  5123. if (isAll && !isAll->queryValue())
  5124. ctx.addAssign(isAll, queryBoolExpr(false));
  5125. }
  5126. localBound.isAll.set(isAll);
  5127. localBound.expr.setown(createValue(no_implicitcast, makeReferenceModifier(LINK(retType)), LINK(strVar)));
  5128. returnByReference = true;
  5129. break;
  5130. }
  5131. case type_table:
  5132. case type_groupedtable:
  5133. {
  5134. if (hasStreamedModifier(retType))
  5135. {
  5136. args.append(*createRowAllocator(ctx, ::queryRecord(retType)));
  5137. break;
  5138. }
  5139. const CHqlBoundTarget * curTarget;
  5140. if (tgt && !tgt->isFixedSize() &&
  5141. (hasLinkCountedModifier(targetType) == hasLinkCountedModifier(retType)))
  5142. {
  5143. doneAssign = true;
  5144. curTarget = tgt;
  5145. }
  5146. else
  5147. {
  5148. curTarget = &localTarget;
  5149. ExpressionFormat format = (hasLinkCountedModifier(retType) ? FormatLinkedDataset : FormatBlockedDataset);
  5150. createTempFor(ctx, retType, localTarget, typemod_none, format);
  5151. }
  5152. if (curTarget->count)
  5153. args.append(*LINK(curTarget->count));
  5154. if (curTarget->length)
  5155. args.append(*LINK(curTarget->length));
  5156. args.append(*createValue(no_reference, curTarget->expr->getType(), LINK(curTarget->expr)));
  5157. if (hasLinkCountedModifier(retType) && hasNonNullRecord(retType) && getBoolProperty(external, allocatorAtom, true))
  5158. args.append(*createRowAllocator(ctx, ::queryRecord(retType)));
  5159. localBound.setFromTarget(*curTarget);
  5160. // localBound.expr.setown(createValue(no_implicitcast, makeReferenceModifier(LINK(retType)), LINK(strVar)));
  5161. returnByReference = true;
  5162. break;
  5163. }
  5164. case type_row:
  5165. {
  5166. if (hasLinkCountedModifier(retType))
  5167. {
  5168. //Always assign link counted rows to a temporary (or the target) to ensure the are not leaked.
  5169. returnMustAssign = true;
  5170. if (tgt && hasLinkCountedModifier(targetType) && recordTypesMatch(targetType, retType))
  5171. {
  5172. doneAssign = true;
  5173. localBound.expr.set(tgt->expr);
  5174. }
  5175. else
  5176. localBound.expr.setown(createWrapperTemp(ctx, retType, typemod_none));
  5177. }
  5178. else
  5179. {
  5180. //row, just pass pointer
  5181. if (tgt && recordTypesMatch(targetType, retType) && !hasLinkCountedModifier(targetType))
  5182. {
  5183. doneAssign = true;
  5184. args.append(*getPointer(tgt->expr));
  5185. localBound.expr.set(tgt->expr);
  5186. }
  5187. else
  5188. {
  5189. resultRow.setown(declareTempRow(ctx, ctx, expr));
  5190. resultRowBuilder.setown(createRowBuilder(ctx, resultRow));
  5191. IHqlExpression * bound = resultRowBuilder->queryBound();
  5192. args.append(*getPointer(bound));
  5193. localBound.expr.set(bound);
  5194. }
  5195. returnByReference = true;
  5196. }
  5197. break;
  5198. }
  5199. case type_transform:
  5200. {
  5201. //Ugly, but target selector is passed in as the target
  5202. assertex(tgt && tgt->expr);
  5203. resultSelfCursor = resolveSelectorDataset(ctx, tgt->expr);
  5204. assertex(resultSelfCursor);
  5205. if (resultSelfCursor->queryBuilder())
  5206. args.append(*LINK(resultSelfCursor->queryBuilder()));
  5207. else
  5208. {
  5209. //Legacy support....
  5210. assertex(!options.supportDynamicRows);
  5211. OwnedHqlExpr rowExpr = getPointer(resultSelfCursor->queryBound());
  5212. StringBuffer builderName;
  5213. getUniqueId(builderName.append("b"));
  5214. StringBuffer s;
  5215. s.append("RtlStaticRowBuilder ").append(builderName).append("(");
  5216. generateExprCpp(s, rowExpr).append(",").append(getMaxRecordSize(funcdef->queryRecord())).append(");");
  5217. ctx.addQuoted(s);
  5218. args.append(*createVariable(builderName, makeBoolType()));
  5219. }
  5220. returnByReference = true;
  5221. doneAssign = true;
  5222. break;
  5223. }
  5224. case type_array:
  5225. UNIMPLEMENTED;
  5226. }
  5227. for (param = firstParam; param < maxParam; param++)
  5228. {
  5229. IHqlExpression * curParam = expr->queryChild(param);
  5230. if (curParam->isAttribute())
  5231. continue;
  5232. if (arg >= maxArg)
  5233. {
  5234. PrintLog("Too many parameters passed to function '%s'", expr->queryName()->str());
  5235. throwError1(HQLERR_TooManyParameters, expr->queryName()->str());
  5236. }
  5237. CHqlBoundExpr bound;
  5238. IHqlExpression * curArg = formals->queryChild(arg);
  5239. ITypeInfo * argType = curArg->queryType();
  5240. OwnedHqlExpr castParam = getCastParameter(curParam, argType);
  5241. type_t atc = argType->getTypeCode();
  5242. switch (atc)
  5243. {
  5244. case type_table:
  5245. case type_groupedtable:
  5246. {
  5247. ExpressionFormat format = queryNaturalFormat(argType);
  5248. buildDataset(ctx, castParam, bound, format);
  5249. break;
  5250. }
  5251. case type_row:
  5252. {
  5253. Owned<IReferenceSelector> selector = buildNewRow(ctx, castParam);
  5254. selector->buildAddress(ctx, bound);
  5255. // buildExpr(ctx, castParam, bound); // more this needs more work I think
  5256. break;
  5257. }
  5258. case type_set:
  5259. {
  5260. ITypeInfo * elemType = argType->queryChildType();
  5261. if (newFormatSet && elemType && (elemType->getTypeCode() != type_any) && (elemType != castParam->queryType()->queryChildType()))
  5262. buildExprEnsureType(ctx, castParam, bound, argType);
  5263. else
  5264. buildExpr(ctx, castParam, bound);
  5265. if (isUnknownSize(elemType))
  5266. {
  5267. ITypeInfo * boundElemType = bound.queryType()->queryChildType();
  5268. assertex(!boundElemType || isUnknownSize(boundElemType));
  5269. }
  5270. normalizeBoundExpr(ctx, bound);
  5271. break;
  5272. }
  5273. case type_decimal:
  5274. {
  5275. buildSimpleExpr(ctx, castParam, bound);
  5276. normalizeBoundExpr(ctx, bound);
  5277. break;
  5278. }
  5279. default:
  5280. {
  5281. buildExpr(ctx, castParam, bound);
  5282. normalizeBoundExpr(ctx, bound);
  5283. break;
  5284. }
  5285. }
  5286. bool done = false;
  5287. switch (atc)
  5288. {
  5289. case type_string:
  5290. case type_data:
  5291. case type_qstring:
  5292. case type_unicode:
  5293. case type_utf8:
  5294. if (argType->getSize() == UNKNOWN_LENGTH)
  5295. args.append(*getBoundLength(bound));
  5296. /*
  5297. Ensure parameter is passed as non-const if the argument does not have const.
  5298. if (!curArg->hasProperty(constAtom))//!argType->isConstantType())// && bound.queryType()->isConstantType())
  5299. bound.expr.setown(createValue(no_cast, LINK(argType), LINK(bound.expr)));
  5300. */
  5301. break;
  5302. case type_varstring:
  5303. case type_varunicode:
  5304. //MORE: pass length only if an out parameter
  5305. break;
  5306. case type_set:
  5307. {
  5308. if (newFormatSet)
  5309. {
  5310. args.append(*bound.getIsAll());
  5311. args.append(*getBoundSize(bound));
  5312. }
  5313. else
  5314. {
  5315. if (castParam->getOperator() == no_all)
  5316. throwError(HQLERR_AllPassedExternal);
  5317. args.append(*getBoundCount(bound));
  5318. }
  5319. break;
  5320. }
  5321. case type_table:
  5322. case type_groupedtable:
  5323. {
  5324. if (isArrayRowset(argType))
  5325. args.append(*getBoundCount(bound));
  5326. else
  5327. args.append(*getBoundSize(bound));
  5328. bound.expr.setown(getPointer(bound.expr));
  5329. break;
  5330. }
  5331. case type_array:
  5332. UNIMPLEMENTED;
  5333. }
  5334. if (!done)
  5335. args.append(*bound.expr.getClear());
  5336. arg++;
  5337. }
  5338. if (arg < maxArg)
  5339. {
  5340. //MORE: Process default parameters...
  5341. PrintLog("Not enough parameters passed to function '%s'", expr->queryName()->str());
  5342. throwError1(HQLERR_TooFewParameters, expr->queryName()->str());
  5343. }
  5344. OwnedHqlExpr call = bindTranslatedFunctionCall(funcdef, args);
  5345. //either copy the integral value across, or a var string to fixed string
  5346. if (returnMustAssign)
  5347. {
  5348. ctx.addAssign(localBound.expr, call);
  5349. }
  5350. else if (resultSelfCursor)
  5351. {
  5352. OwnedHqlExpr sizeVar = ctx.getTempDeclare(unsignedType, call);
  5353. OwnedHqlExpr sizeOfExpr = createSizeof(resultSelfCursor->querySelector());
  5354. ctx.associateExpr(sizeOfExpr, sizeVar);
  5355. }
  5356. else if (returnByReference || (!tgt && !result))
  5357. {
  5358. ctx.addExpr(call);
  5359. if (translateSetReturn && tgt)
  5360. {
  5361. CHqlBoundTarget targetLength;
  5362. CHqlBoundExpr boundLength;
  5363. boundLength.expr.setown(getBoundLength(localBound));
  5364. targetLength.expr.set(tgt->length);
  5365. assign(ctx, targetLength, boundLength);
  5366. }
  5367. }
  5368. else
  5369. localBound.expr.set(call);
  5370. if (localBound.expr)
  5371. localBound.expr.setown(convertWrapperToPointer(localBound.expr));
  5372. if (tgt && !doneAssign)
  5373. assign(ctx, *tgt, localBound);
  5374. else if (result)
  5375. result->set(localBound);
  5376. //Old style row target where the row is passed in as a parameter
  5377. if (resultRow)
  5378. finalizeTempRow(ctx, resultRow, resultRowBuilder);
  5379. if (returnByReference)
  5380. ctx.associateExpr(expr, localBound);
  5381. }
  5382. void HqlCppTranslator::doBuildExprCall(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  5383. {
  5384. doBuildCall(ctx, NULL, expr, &tgt);
  5385. }
  5386. void HqlCppTranslator::doBuildAssignCall(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  5387. {
  5388. ITypeInfo * exprType = expr->queryType()->queryPromotedType();
  5389. if ((exprType->getSize() == UNKNOWN_LENGTH) && target.isFixedSize())
  5390. {
  5391. doBuildExprAssign(ctx, target, expr);
  5392. return;
  5393. }
  5394. ITypeInfo * targetType = target.queryType()->queryPromotedType();
  5395. if ((isStringType(exprType) || isUnicodeType(exprType) || isStringType(targetType) || isUnicodeType(targetType)) && exprType->getTypeCode() != targetType->getTypeCode())
  5396. {
  5397. doBuildExprAssign(ctx, target, expr);
  5398. return;
  5399. }
  5400. if ((exprType->getTypeCode() == type_set) && (queryUnqualifiedType(targetType) != queryUnqualifiedType(exprType)))
  5401. {
  5402. if (exprType->queryChildType()) // allow direct assignment of generic set functions. (e.g., internal)
  5403. {
  5404. doBuildExprAssign(ctx, target, expr);
  5405. return;
  5406. }
  5407. }
  5408. doBuildCall(ctx, &target, expr, NULL);
  5409. }
  5410. void HqlCppTranslator::doBuildStmtCall(BuildCtx & ctx, IHqlExpression * expr)
  5411. {
  5412. doBuildCall(ctx, NULL, expr, NULL);
  5413. }
  5414. //---------------------------------------------------------------------------
  5415. void HqlCppTranslator::doBuildXmlEncode(BuildCtx & ctx, const CHqlBoundTarget * tgt, IHqlExpression * expr, CHqlBoundExpr * result)
  5416. {
  5417. node_operator op = expr->getOperator();
  5418. bool isUnicode = isUnicodeType(expr->queryType());
  5419. HqlExprArray args;
  5420. _ATOM func;
  5421. args.append(*LINK(expr->queryChild(0)));
  5422. if (op == no_xmldecode)
  5423. func = isUnicode ? xmlDecodeUStrAtom : xmlDecodeStrAtom;
  5424. else
  5425. {
  5426. func = isUnicode ? xmlEncodeUStrAtom : xmlEncodeStrAtom;
  5427. __int64 flags = 0;
  5428. if (expr->hasProperty(allAtom))
  5429. flags = ENCODE_WHITESPACE;
  5430. args.append(*createConstant(flags));
  5431. }
  5432. OwnedHqlExpr call = bindFunctionCall(func, args);
  5433. if (tgt)
  5434. buildExprAssign(ctx, *tgt, call);
  5435. else
  5436. buildExpr(ctx, call, *result);
  5437. }
  5438. //---------------------------------------------------------------------------
  5439. //-- no_cast --
  5440. //-- no_implicitcast --
  5441. IValue * getCastValue(ITypeInfo * cast, IHqlExpression * arg)
  5442. {
  5443. Owned<IValue> value;
  5444. switch (arg->getOperator())
  5445. {
  5446. case no_constant:
  5447. value.set(arg->queryValue());
  5448. break;
  5449. case no_cast: case no_implicitcast:
  5450. value.setown(getCastValue(arg->queryType(), arg->queryChild(0)));
  5451. break;
  5452. default:
  5453. return NULL;
  5454. }
  5455. if (!value)
  5456. return NULL;
  5457. return value->castTo(cast);
  5458. }
  5459. inline IHqlExpression * getCastExpr(ITypeInfo * cast, IHqlExpression * arg)
  5460. {
  5461. IValue * value = getCastValue(cast, arg);
  5462. if (value)
  5463. return createConstant(value);
  5464. return NULL;
  5465. }
  5466. void HqlCppTranslator::doBuildAssignCast(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  5467. {
  5468. IHqlExpression * left = expr->queryChild(0);
  5469. if (options.foldConstantCast)
  5470. {
  5471. //remove when we have constant folding installed...
  5472. OwnedHqlExpr cast = getCastExpr(expr->queryType(), left);
  5473. if (cast)
  5474. {
  5475. buildExprAssign(ctx, target, cast);
  5476. return;
  5477. }
  5478. }
  5479. #if 0
  5480. StringBuffer s;
  5481. s.append("assign cast from=");
  5482. left->queryType()->getECLType(s);
  5483. target.queryType()->getECLType(s.append(" target="));
  5484. expr->queryType()->getECLType(s.append(" expr="));
  5485. PrintLog(s.str());
  5486. #endif
  5487. ITypeInfo * targetType = target.queryType();
  5488. ITypeInfo * exprType = expr->queryType();
  5489. if ((targetType->queryPromotedType() == exprType->queryPromotedType()))
  5490. {
  5491. CHqlBoundExpr bound;
  5492. if (ctx.getMatchExpr(left, bound))
  5493. assignAndCast(ctx, target, bound);
  5494. else
  5495. {
  5496. OwnedHqlExpr values = normalizeListCasts(expr);
  5497. if (values != expr)
  5498. {
  5499. buildExprAssign(ctx, target, values);
  5500. return;
  5501. }
  5502. node_operator leftOp = left->getOperator();
  5503. bool useTemp = requiresTemp(ctx, left, false) && (leftOp != no_concat) && (leftOp != no_createset);
  5504. if (useTemp && target.isFixedSize())
  5505. {
  5506. bool ignoreStretched = false;
  5507. switch (leftOp)
  5508. {
  5509. case no_case:
  5510. case no_map:
  5511. //MORE: If the length of the bulk of the branches match then it is worth ignoring.
  5512. //would be worthwhile if isStringType(targetType) || isUnicodeType(targetType);
  5513. break;
  5514. case no_substring:
  5515. //don't do this if the target type is unicode at the moment
  5516. ignoreStretched = isStringType(targetType);
  5517. break;
  5518. }
  5519. if (ignoreStretched)
  5520. {
  5521. Owned<ITypeInfo> stretchedType = getStretchedType(targetType->getStringLen(), exprType);
  5522. if (isSameBasicType(stretchedType, targetType->queryPromotedType()))
  5523. useTemp = false;
  5524. }
  5525. }
  5526. if (useTemp)
  5527. {
  5528. buildExpr(ctx, left, bound);
  5529. assignAndCast(ctx, target, bound);
  5530. }
  5531. else
  5532. {
  5533. buildExprAssign(ctx, target, left);
  5534. }
  5535. }
  5536. return;
  5537. }
  5538. ITypeInfo * leftType = left->queryType();
  5539. if ((targetType->queryPromotedType() == left->queryType()->queryPromotedType()))
  5540. {
  5541. if (preservesValue(exprType, leftType))
  5542. {
  5543. buildExprAssign(ctx, target, left);
  5544. return;
  5545. }
  5546. }
  5547. CHqlBoundExpr pure;
  5548. bool assignDirect = false;
  5549. if ((exprType->getSize() == UNKNOWN_LENGTH) && (targetType->getTypeCode() == exprType->getTypeCode()) &&
  5550. (isStringType(exprType) || isUnicodeType(exprType)))
  5551. {
  5552. OwnedITypeInfo stretched = getStretchedType(UNKNOWN_LENGTH, targetType->queryPromotedType());
  5553. if (stretched == exprType->queryPromotedType())
  5554. assignDirect = true;
  5555. }
  5556. if (assignDirect)
  5557. buildExpr(ctx, left, pure);
  5558. else
  5559. buildExpr(ctx, expr, pure);
  5560. assignAndCast(ctx, target, pure);
  5561. }
  5562. void HqlCppTranslator::doBuildExprCast(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  5563. {
  5564. IHqlExpression * arg = expr->queryChild(0);
  5565. ITypeInfo * exprType = expr->queryType();
  5566. if (exprType->getTypeCode() == type_set)
  5567. {
  5568. OwnedHqlExpr castArg = ensureExprType(arg, exprType);
  5569. if ((castArg->getOperator() != no_cast) && (castArg->getOperator() != no_implicitcast))
  5570. {
  5571. buildExpr(ctx, castArg, tgt);
  5572. return;
  5573. }
  5574. //The case is almost certainly going to go via a temporary anyway, better code is generated if we can avoid an extra assign
  5575. buildTempExpr(ctx, expr, tgt);
  5576. return;
  5577. }
  5578. if (options.foldConstantCast)
  5579. {
  5580. //remove when we have constant folding installed...
  5581. IHqlExpression * cast = getCastExpr(exprType, arg);
  5582. if (cast)
  5583. {
  5584. tgt.expr.setown(cast);
  5585. return;
  5586. }
  5587. }
  5588. // weird special case.... (int4)(swapint4)int4_x - remove both casts...
  5589. switch (arg->getOperator())
  5590. {
  5591. case no_cast:
  5592. case no_implicitcast:
  5593. {
  5594. IHqlExpression * child = arg->queryChild(0);
  5595. if (child->queryType() == exprType)
  5596. {
  5597. if ((exprType->getTypeCode() == type_int) || (exprType->getTypeCode() == type_swapint) || (exprType->getTypeCode() == type_packedint))
  5598. {
  5599. ITypeInfo * argType = arg->queryType();
  5600. if ((argType->getTypeCode() == type_int) || (argType->getTypeCode() == type_swapint) || (argType->getTypeCode() == type_packedint))
  5601. {
  5602. if (argType->getSize() == exprType->getSize())
  5603. {
  5604. buildExpr(ctx, child, tgt);
  5605. return;
  5606. }
  5607. }
  5608. }
  5609. }
  5610. break;
  5611. }
  5612. #if 0
  5613. case no_if:
  5614. {
  5615. //optimize cast of an if where one of the arguments is already the correct type
  5616. //this doesn't really improve things
  5617. IHqlExpression * lhs = arg->queryChild(1);
  5618. IHqlExpression * rhs = arg->queryChild(2);
  5619. if (lhs->queryType() == exprType || lhs->getOperator() == no_constant ||
  5620. rhs->queryType() == exprType || rhs->getOperator() == no_constant)
  5621. {
  5622. HqlExprArray args;
  5623. args.append(*LINK(arg->queryChild(0)));
  5624. args.append(*ensureExprType(lhs, exprType));
  5625. args.append(*ensureExprType(rhs, exprType));
  5626. unwindChildren(args, arg, 3);
  5627. OwnedHqlExpr next = createValue(no_if, LINK(exprType), args);
  5628. buildExpr(ctx, next, tgt);
  5629. return;
  5630. }
  5631. break;
  5632. }
  5633. #endif
  5634. case no_substring:
  5635. {
  5636. ITypeInfo * argType = arg->queryType();
  5637. if ((exprType->getSize() != UNKNOWN_LENGTH) && (argType->getSize() == UNKNOWN_LENGTH) && (exprType->getTypeCode() == argType->getTypeCode()))
  5638. {
  5639. OwnedITypeInfo stretched = getStretchedType(exprType->getStringLen(), argType);
  5640. if (stretched == exprType)
  5641. {
  5642. buildTempExpr(ctx, expr, tgt);
  5643. return;
  5644. }
  5645. }
  5646. break;
  5647. }
  5648. }
  5649. CHqlBoundExpr pure;
  5650. buildExpr(ctx, arg, pure);
  5651. doBuildExprCast(ctx, exprType, pure, tgt);
  5652. if ((arg->queryType()->getTypeCode() == type_decimal) && !isTypePassedByAddress(exprType))
  5653. {
  5654. OwnedHqlExpr translated = tgt.getTranslatedExpr();
  5655. buildTempExpr(ctx, translated, tgt);
  5656. }
  5657. }
  5658. void HqlCppTranslator::doBuildCastViaTemp(BuildCtx & ctx, ITypeInfo * to, CHqlBoundExpr & pure, CHqlBoundExpr & tgt)
  5659. {
  5660. CHqlBoundTarget boundTarget;
  5661. Linked<ITypeInfo> targetType = to;
  5662. //If the temporary size can be deduced, then use a fixed length temporary to save a heap operation.
  5663. ITypeInfo * fromType = pure.expr->queryType();
  5664. if (isStringType(to) && to->getSize() == UNKNOWN_LENGTH && isStringType(fromType) && !pure.length)
  5665. {
  5666. assertex(fromType->getSize() != UNKNOWN_LENGTH);
  5667. targetType.setown(getStretchedType(fromType->getStringLen(), to));
  5668. }
  5669. OwnedHqlExpr translated = pure.getTranslatedExpr();
  5670. OwnedHqlExpr cast = ensureExprType(translated, targetType);
  5671. buildTempExpr(ctx, cast, tgt);
  5672. }
  5673. void HqlCppTranslator::doBuildCastViaString(BuildCtx & ctx, ITypeInfo * to, const CHqlBoundExpr & pure, CHqlBoundExpr & tgt)
  5674. {
  5675. ITypeInfo * from = pure.expr->queryType();
  5676. Owned<ITypeInfo> tempType = makeStringType(from->getStringLen(), NULL, NULL);
  5677. OwnedHqlExpr temp = createValue(no_implicitcast, LINK(to),
  5678. createValue(no_implicitcast, tempType.getLink(), pure.getTranslatedExpr()));
  5679. buildExpr(ctx, temp, tgt);
  5680. }
  5681. void HqlCppTranslator::doBuildExprCast(BuildCtx & ctx, ITypeInfo * to, CHqlBoundExpr & pure, CHqlBoundExpr & tgt)
  5682. {
  5683. ITypeInfo * from = pure.expr->queryType();
  5684. HqlExprArray args;
  5685. _ATOM funcName = NULL;
  5686. OwnedHqlExpr op;
  5687. switch (to->getTypeCode())
  5688. {
  5689. case type_boolean:
  5690. {
  5691. switch (from->getTypeCode())
  5692. {
  5693. case type_string:
  5694. funcName = an2bAtom;
  5695. args.append(*getBoundLength(pure));
  5696. args.append(*getElementPointer(pure.expr));
  5697. break;
  5698. case type_data:
  5699. funcName = data2BoolAtom;
  5700. args.append(*getBoundLength(pure));
  5701. args.append(*getElementPointer(pure.expr));
  5702. break;
  5703. case type_qstring:
  5704. funcName = qstr2BoolAtom;
  5705. args.append(*getBoundLength(pure));
  5706. args.append(*getElementPointer(pure.expr));
  5707. break;
  5708. case type_varstring:
  5709. funcName = vn2bAtom;
  5710. args.append(*getElementPointer(pure.expr));
  5711. break;
  5712. case type_decimal:
  5713. ensurePushed(ctx, pure);
  5714. funcName = DecCompareNullAtom;
  5715. break;
  5716. case type_unicode:
  5717. case type_varunicode:
  5718. case type_utf8:
  5719. doBuildCastViaString(ctx, to, pure, tgt);
  5720. return;
  5721. case type_real:
  5722. default:
  5723. //default action
  5724. break;
  5725. }
  5726. break;
  5727. }
  5728. case type_packedint:
  5729. {
  5730. ITypeInfo * logicalType = to->queryPromotedType();
  5731. size32_t toSize = logicalType->getSize();
  5732. if ((from->getTypeCode() != type_int) || (toSize != from->getSize()))
  5733. {
  5734. OwnedHqlExpr translated = pure.getTranslatedExpr();
  5735. OwnedHqlExpr castTranslated = createValue(no_implicitcast, LINK(logicalType), LINK(translated));
  5736. buildExpr(ctx, castTranslated, tgt);
  5737. return;
  5738. }
  5739. tgt.set(pure);
  5740. return;
  5741. }
  5742. case type_swapint:
  5743. {
  5744. if ((from->getTypeCode() == type_swapint) && (to->getSize() == from->getSize()))
  5745. {
  5746. break; // default behaviour
  5747. //MORE: Could special case cast between diff size swapints, but a bit too complicated.
  5748. }
  5749. if (from->getTypeCode() != type_int)
  5750. {
  5751. ITypeInfo * tempType = makeIntType(to->getSize(), to->isSigned());
  5752. IHqlExpression * translated = pure.getTranslatedExpr();
  5753. translated = createValue(no_implicitcast, tempType, translated);
  5754. OwnedHqlExpr castTranslated = createValue(no_implicitcast, LINK(to), translated);
  5755. buildExpr(ctx, castTranslated, tgt);
  5756. return;
  5757. }
  5758. unsigned toSize = to->getSize();
  5759. unsigned fromSize = from->getSize();
  5760. if ((toSize == 1) && (fromSize == 1))
  5761. {
  5762. if (to->isSigned() != from->isSigned())
  5763. break;
  5764. tgt.expr.setown(createValue(no_typetransfer, LINK(to), LINK(pure.expr)));
  5765. return;
  5766. }
  5767. if (toSize != fromSize)
  5768. {
  5769. Owned<ITypeInfo> tempType = makeIntType(toSize, from->isSigned());
  5770. CHqlBoundExpr tempInt;
  5771. tempInt.expr.setown(ensureExprType(pure.expr, tempType));
  5772. doBuildCastViaTemp(ctx, to, tempInt, tgt);
  5773. }
  5774. else
  5775. doBuildCastViaTemp(ctx, to, pure, tgt);
  5776. return;
  5777. }
  5778. case type_int:
  5779. {
  5780. switch (from->getTypeCode())
  5781. {
  5782. case type_qstring:
  5783. {
  5784. //Need to go via a temporary string.
  5785. Owned<ITypeInfo> tempType = makeStringType(from->getStringLen(), NULL, NULL);
  5786. OwnedHqlExpr temp = createValue(no_implicitcast, LINK(to),
  5787. createValue(no_implicitcast, tempType.getLink(), pure.getTranslatedExpr()));
  5788. buildExpr(ctx, temp, tgt);
  5789. return;
  5790. }
  5791. case type_string:
  5792. case type_data:
  5793. {
  5794. _ATOM charset = from->queryCharset()->queryName();
  5795. if (charset == ebcdicAtom)
  5796. {
  5797. if (to->isSigned())
  5798. funcName = (to->getSize() > 4 ? en2ls8Atom : en2ls4Atom);
  5799. else
  5800. funcName = (to->getSize() > 4 ? en2l8Atom : en2l4Atom);
  5801. }
  5802. else if ((charset == asciiAtom) || (charset == dataAtom))
  5803. {
  5804. if (to->isSigned())
  5805. funcName = (to->getSize() > 4 ? an2ls8Atom : an2ls4Atom);
  5806. else
  5807. funcName = (to->getSize() > 4 ? an2l8Atom : an2l4Atom);
  5808. }
  5809. else
  5810. assertex(!"Unknown character set");
  5811. //MORE: This should really cast the result to the real width to remove extra bytes.
  5812. //e.g. (unsigned3)-1 should be 0xffffff, not 0xffffffff
  5813. args.append(*getBoundLength(pure));
  5814. args.append(*getElementPointer(pure.expr));
  5815. break;
  5816. }
  5817. case type_varstring:
  5818. if (to->isSigned())
  5819. funcName = (to->getSize() > 4 ? vn2ls8Atom : vn2ls4Atom);
  5820. else
  5821. funcName = (to->getSize() > 4 ? vn2l8Atom : vn2l4Atom);
  5822. args.append(*getElementPointer(pure.expr));
  5823. break;
  5824. case type_decimal:
  5825. ensurePushed(ctx, pure);
  5826. if (to->getSize() > 4)
  5827. funcName = DecPopInt64Atom;
  5828. else
  5829. funcName = DecPopLongAtom;
  5830. break;
  5831. case type_packedint:
  5832. {
  5833. if (to->getSize() < from->getSize())
  5834. {
  5835. funcName = castIntAtom[to->getSize()][to->isSigned()];
  5836. args.append(*LINK(pure.expr));
  5837. }
  5838. else
  5839. tgt.set(pure);
  5840. break;
  5841. }
  5842. case type_swapint:
  5843. {
  5844. unsigned toSize = to->getSize();
  5845. unsigned fromSize = from->getSize();
  5846. if ((toSize == 1) && (fromSize == 1))
  5847. {
  5848. if (to->isSigned() != from->isSigned())
  5849. break;
  5850. tgt.expr.setown(createValue(no_typetransfer, LINK(to), LINK(pure.expr)));
  5851. return;
  5852. }
  5853. if (toSize != fromSize)
  5854. {
  5855. Owned<ITypeInfo> tempType = makeIntType(fromSize, from->isSigned());
  5856. CHqlBoundExpr tempInt;
  5857. doBuildCastViaTemp(ctx, tempType, pure, tempInt);
  5858. funcName = castIntAtom[to->getSize()][to->isSigned()];
  5859. if (funcName && toSize < fromSize)
  5860. {
  5861. args.append(*LINK(tempInt.expr));
  5862. tgt.expr.setown(bindTranslatedFunctionCall(funcName, args));
  5863. }
  5864. else
  5865. tgt.expr.setown(ensureExprType(tempInt.expr, to));
  5866. }
  5867. else
  5868. doBuildCastViaTemp(ctx, to, pure, tgt);
  5869. return;
  5870. }
  5871. case type_int:
  5872. if (to->getSize() < from->getSize())
  5873. {
  5874. _ATOM name = castIntAtom[to->getSize()][to->isSigned()];
  5875. if (name)
  5876. {
  5877. args.append(*LINK(pure.expr));
  5878. IHqlExpression * call = bindTranslatedFunctionCall(name, args);
  5879. op.setown(createValue(no_typetransfer, LINK(to), call));
  5880. }
  5881. }
  5882. break;
  5883. case type_unicode:
  5884. case type_varunicode:
  5885. case type_utf8:
  5886. doBuildCastViaString(ctx, to, pure, tgt);
  5887. return;
  5888. case type_real:
  5889. default:
  5890. //default action
  5891. break;
  5892. }
  5893. break;
  5894. }
  5895. case type_real:
  5896. switch (from->getTypeCode())
  5897. {
  5898. case type_qstring:
  5899. case type_unicode:
  5900. case type_varunicode:
  5901. case type_utf8:
  5902. doBuildCastViaString(ctx, to, pure, tgt);
  5903. return;
  5904. case type_data:
  5905. case type_string:
  5906. funcName = from->queryCharset()->queryName() != ebcdicAtom ? an2fAtom : en2fAtom;
  5907. args.append(*getBoundLength(pure));
  5908. args.append(*getElementPointer(pure.expr));
  5909. break;
  5910. case type_varstring:
  5911. funcName = from->queryCharset()->queryName() != ebcdicAtom ? vn2fAtom : ex2fAtom;
  5912. args.append(*getElementPointer(pure.expr));
  5913. break;
  5914. case type_decimal:
  5915. ensurePushed(ctx, pure);
  5916. funcName = DecPopRealAtom;
  5917. break;
  5918. case type_swapint:
  5919. {
  5920. //cast via intermediate int.
  5921. ITypeInfo * type = makeIntType(from->getSize(), from->isSigned());
  5922. IHqlExpression * translated = pure.getTranslatedExpr();
  5923. OwnedHqlExpr castTranslated = createValue(no_implicitcast, type, translated);
  5924. pure.clear();
  5925. buildExpr(ctx, castTranslated, pure);
  5926. from = type;
  5927. }
  5928. //fallthrough
  5929. case type_int:
  5930. case type_boolean:
  5931. case type_packedint:
  5932. default:
  5933. //default action
  5934. break;
  5935. }
  5936. break;
  5937. case type_decimal:
  5938. {
  5939. ensurePushed(ctx, pure);
  5940. bool needToSetPrecision = true;
  5941. unsigned toDigits = to->getDigits();
  5942. unsigned toPrecision = to->getPrecision();
  5943. switch (from->getTypeCode())
  5944. {
  5945. case type_int:
  5946. case type_swapint:
  5947. if (toDigits >= from->getDigits())
  5948. needToSetPrecision = false;
  5949. break;
  5950. case type_decimal:
  5951. {
  5952. unsigned fromDigits = from->getDigits();
  5953. unsigned fromPrecision = from->getPrecision();
  5954. if (((toDigits - toPrecision) >= (fromDigits - fromPrecision)) &&
  5955. (toPrecision >= fromPrecision))
  5956. needToSetPrecision = false;
  5957. break;
  5958. }
  5959. }
  5960. if ((toDigits == MAX_DECIMAL_DIGITS) && (toPrecision == MAX_DECIMAL_PRECISION))
  5961. needToSetPrecision = false;
  5962. if (needToSetPrecision)
  5963. {
  5964. args.append(*createConstant(createIntValue(to->getDigits(), 1, false)));
  5965. args.append(*createConstant(createIntValue(to->getPrecision(), 1, false)));
  5966. callProcedure(ctx, DecSetPrecisionAtom, args);
  5967. }
  5968. op.setown(createValue(no_decimalstack, LINK(to)));
  5969. }
  5970. break;
  5971. case type_set:
  5972. {
  5973. //MORE: Shouldn't have to create this node...
  5974. OwnedHqlExpr cast = createValue(no_implicitcast, LINK(to), pure.getTranslatedExpr());
  5975. buildTempExpr(ctx, cast, tgt);
  5976. return;
  5977. }
  5978. case type_pointer:
  5979. case type_row:
  5980. break;
  5981. case type_varstring:
  5982. if ((to->getSize() == UNKNOWN_LENGTH) && (from->getTypeCode() == type_varstring))
  5983. tgt.set(pure);
  5984. else
  5985. doBuildCastViaTemp(ctx, to, pure, tgt);
  5986. return;
  5987. case type_string:
  5988. case type_data:
  5989. {
  5990. if (canRemoveStringCast(to, from))
  5991. {
  5992. ICharsetInfo * srcset = from->queryCharset();
  5993. ICharsetInfo * tgtset = to->queryCharset();
  5994. //Data never calls a conversion function... but does add a cast
  5995. if ((srcset == tgtset) || (to->getTypeCode() == type_data) || (from->getTypeCode() == type_data))
  5996. {
  5997. if (from->getTypeCode() == type_varstring)
  5998. tgt.length.setown(getBoundLength(pure));
  5999. else
  6000. tgt.length.set(pure.length);
  6001. Owned<ITypeInfo> newType;
  6002. if (to->getSize() == UNKNOWN_LENGTH)
  6003. newType.setown(getStretchedType(from->getSize(), to));
  6004. else
  6005. newType.set(to);
  6006. if (from->getTypeCode() != type_data)
  6007. {
  6008. newType.setown(cloneModifiers(from, newType));
  6009. tgt.expr.setown(createValue(no_typetransfer, newType.getClear(), pure.expr.getLink()));
  6010. }
  6011. else
  6012. {
  6013. IHqlExpression * base = queryStripCasts(pure.expr);
  6014. newType.setown(makeReferenceModifier(newType.getClear()));
  6015. tgt.expr.setown(createValue(no_cast, newType.getClear(), LINK(base)));
  6016. }
  6017. return;
  6018. }
  6019. }
  6020. }
  6021. doBuildCastViaTemp(ctx, to, pure, tgt);
  6022. return;
  6023. case type_unicode:
  6024. case type_varunicode:
  6025. if ((from->getTypeCode() == to->getTypeCode()) && (to->getSize() == UNKNOWN_LENGTH))
  6026. {
  6027. tgt.set(pure);
  6028. return;
  6029. }
  6030. doBuildCastViaTemp(ctx, to, pure, tgt);
  6031. return;
  6032. default:
  6033. doBuildCastViaTemp(ctx, to, pure, tgt);
  6034. return;
  6035. }
  6036. if (funcName)
  6037. op.setown(bindTranslatedFunctionCall(funcName, args));
  6038. if (!op)
  6039. op.setown(ensureExprType(pure.expr, to));
  6040. if (queryUnqualifiedType(op->queryType()) != queryUnqualifiedType(to))
  6041. {
  6042. OwnedHqlExpr translated = createTranslated(op);
  6043. OwnedHqlExpr cast = ensureExprType(translated, to);
  6044. buildExpr(ctx, cast, tgt);
  6045. }
  6046. else
  6047. tgt.expr.setown(op.getClear());
  6048. }
  6049. //---------------------------------------------------------------------------
  6050. //-- no_char_length --
  6051. //NB: parameter is expression to take length of - not the length node.
  6052. IHqlExpression * HqlCppTranslator::doBuildCharLength(BuildCtx & ctx, IHqlExpression * expr)
  6053. {
  6054. CHqlBoundExpr bound;
  6055. buildCachedExpr(ctx, expr, bound);
  6056. return getBoundLength(bound);
  6057. }
  6058. //---------------------------------------------------------------------------
  6059. //-- no_choose
  6060. void HqlCppTranslator::doBuildChoose(BuildCtx & ctx, const CHqlBoundTarget * target, IHqlExpression * expr)
  6061. {
  6062. CHqlBoundExpr test;
  6063. BuildCtx subctx(ctx);
  6064. buildExpr(subctx, expr->queryChild(0), test);
  6065. IHqlStmt * stmt = subctx.addSwitch(test.expr);
  6066. unsigned max = expr->numChildren()-1;
  6067. unsigned idx;
  6068. for (idx = 1; idx < max; idx++)
  6069. {
  6070. OwnedHqlExpr branch = getSizetConstant(idx);
  6071. subctx.addCase(stmt, branch);
  6072. buildExprOrAssign(subctx, target, expr->queryChild(idx), NULL);
  6073. }
  6074. subctx.addDefault(stmt);
  6075. buildExprOrAssign(subctx, target, expr->queryChild(max), NULL);
  6076. }
  6077. void HqlCppTranslator::doBuildAssignChoose(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6078. {
  6079. unsigned max = expr->numChildren()-1;
  6080. unsigned idx;
  6081. bool allConstant = true;
  6082. for (idx = 1; idx < max; idx++)
  6083. {
  6084. if (!expr->queryChild(idx)->queryValue())
  6085. allConstant = false;
  6086. }
  6087. if (allConstant)
  6088. {
  6089. //MORE: Need to calculate the correct type.
  6090. HqlExprArray args;
  6091. args.append(*LINK(expr->queryChild(0)));
  6092. for (idx = 1; idx < max; idx++)
  6093. {
  6094. IHqlExpression * v1 = createConstant(createIntValue(idx, LINK(unsignedType)));
  6095. IHqlExpression * v2 = expr->queryChild(idx);
  6096. ITypeInfo * type = v2->queryType();
  6097. args.append(* createValue(no_mapto, LINK(type), v1, LINK(v2)));
  6098. }
  6099. args.append(*LINK(expr->queryChild(max)));
  6100. OwnedHqlExpr caseExpr = createValue(no_case, expr->getType(), args);
  6101. buildExprAssign(ctx, target, caseExpr);
  6102. }
  6103. else
  6104. {
  6105. doBuildChoose(ctx, &target, expr);
  6106. }
  6107. }
  6108. //---------------------------------------------------------------------------
  6109. //-- compare (no_eq,no_ne,no_lt,no_gt,no_le,no_ge) --
  6110. //Are the arguments scalar? If so return the scalar arguments.
  6111. static bool getIsScalarCompare(IHqlExpression * expr, SharedHqlExpr & left, SharedHqlExpr & right)
  6112. {
  6113. left.set(expr->queryChild(0));
  6114. right.set(expr->queryChild(1));
  6115. ITypeInfo * lType = left->queryType();
  6116. ITypeInfo * rType = right->queryType();
  6117. type_t leftTypeCode = lType ? lType->getTypeCode() : type_row;
  6118. type_t rightTypeCode = rType ? rType->getTypeCode() : type_row;
  6119. assertex(leftTypeCode == rightTypeCode);
  6120. switch (leftTypeCode)
  6121. {
  6122. case type_row:
  6123. case type_set:
  6124. return false;
  6125. default:
  6126. return true;
  6127. }
  6128. }
  6129. void HqlCppTranslator::doBuildAssignCompare(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6130. {
  6131. OwnedHqlExpr left;
  6132. OwnedHqlExpr right;
  6133. if (getIsScalarCompare(expr, left, right))
  6134. {
  6135. doBuildExprAssign(ctx, target, expr);
  6136. return;
  6137. }
  6138. //Comparing a row - calculate the ordering and then compare against zero...
  6139. IHqlExpression * compare = createValue(no_order, LINK(signedType), LINK(left), LINK(right));
  6140. OwnedHqlExpr temp = createBoolExpr(expr->getOperator(), compare, getZero());
  6141. buildExprAssign(ctx, target, temp);
  6142. }
  6143. //---------------------------------------------------------------------------
  6144. //-- no_concat --
  6145. void HqlCppTranslator::buildConcatFArgs(HqlExprArray & args, BuildCtx & ctx, const HqlExprArray & values, ITypeInfo * argType)
  6146. {
  6147. ForEachItemIn(idx, values)
  6148. {
  6149. IHqlExpression * cur = &values.item(idx);
  6150. OwnedHqlExpr value = getCastParameter(cur, argType);
  6151. CHqlBoundExpr bound;
  6152. buildCachedExpr(ctx, value, bound);
  6153. //The function takes ... so the length must be 4 bytes or the stack
  6154. //gets out of sync...
  6155. OwnedHqlExpr length = getBoundLength(bound);
  6156. args.append(*ensureExprType(length, unsignedType));
  6157. args.append(*getElementPointer(bound.expr));
  6158. }
  6159. args.append(*createConstant(signedType->castFrom(true, -1))); // correct size terminator
  6160. }
  6161. void HqlCppTranslator::doBuildVarLengthConcatF(BuildCtx & ctx, const CHqlBoundTarget & target, const HqlExprArray & values)
  6162. {
  6163. ITypeInfo * targetType = target.queryType();
  6164. Linked<ITypeInfo> argType = targetType;
  6165. type_t ttc = targetType->getTypeCode();
  6166. HqlExprArray args;
  6167. _ATOM func;
  6168. if (ttc == type_varstring)
  6169. {
  6170. func = concatVStrAtom;
  6171. argType.setown(makeStringType(UNKNOWN_LENGTH, LINK(targetType->queryCharset()), LINK(targetType->queryCollation())));
  6172. }
  6173. else if (ttc == type_unicode)
  6174. {
  6175. args.append(*target.length.getLink());
  6176. func = concatUnicodeAtom;
  6177. }
  6178. else if (ttc == type_utf8)
  6179. {
  6180. args.append(*target.length.getLink());
  6181. func = concatUtf8Atom;
  6182. }
  6183. else if (ttc == type_varunicode)
  6184. {
  6185. func = concatVUnicodeAtom;
  6186. argType.setown(makeUnicodeType(UNKNOWN_LENGTH, targetType->queryLocale()));
  6187. }
  6188. else
  6189. {
  6190. args.append(*target.length.getLink());
  6191. func = concatAtom;
  6192. }
  6193. IHqlExpression * tgt = createValue(no_address, makeVoidType(), LINK(target.expr));
  6194. if (ttc == type_data)
  6195. tgt = createValue(no_implicitcast, makePointerType(makeStringType(UNKNOWN_LENGTH, NULL, NULL)), tgt);
  6196. args.append(*tgt);
  6197. buildConcatFArgs(args, ctx, values, argType);
  6198. callProcedure(ctx, func, args);
  6199. }
  6200. bool HqlCppTranslator::doBuildFixedLengthConcatF(BuildCtx & ctx, const CHqlBoundTarget & target, const HqlExprArray & values)
  6201. {
  6202. ITypeInfo * targetType = target.queryType();
  6203. Owned<ITypeInfo> argType = getStretchedType(UNKNOWN_LENGTH, targetType);
  6204. type_t ttc = targetType->getTypeCode();
  6205. HqlExprArray args;
  6206. _ATOM func = NULL;
  6207. OwnedHqlExpr fill;
  6208. switch (ttc)
  6209. {
  6210. case type_varstring:
  6211. func = concatVStrFAtom;
  6212. argType.setown(makeStringType(UNKNOWN_LENGTH, LINK(targetType->queryCharset()), LINK(targetType->queryCollation())));
  6213. break;
  6214. case type_varunicode:
  6215. func = concatVUnicodeFAtom;
  6216. argType.setown(makeUnicodeType(UNKNOWN_LENGTH, targetType->queryLocale()));
  6217. break;
  6218. case type_unicode:
  6219. func = concatUnicodeFAtom;
  6220. break;
  6221. case type_string:
  6222. func = concatStrFAtom;
  6223. if (targetType->queryCharset()->queryName() == ebcdicAtom)
  6224. fill.setown(getSizetConstant('@'));
  6225. else
  6226. fill.setown(getSizetConstant(' '));
  6227. break;
  6228. case type_data:
  6229. func = concatStrFAtom;
  6230. fill.setown(getSizetConstant(0));
  6231. break;
  6232. }
  6233. if (func)
  6234. {
  6235. args.append(*getSizetConstant(targetType->getStringLen()));
  6236. args.append(*getPointer(target.expr));
  6237. if (fill)
  6238. args.append(*LINK(fill));
  6239. buildConcatFArgs(args, ctx, values, argType);
  6240. callProcedure(ctx, func, args);
  6241. return true;
  6242. }
  6243. return false;
  6244. }
  6245. void HqlCppTranslator::doBuildAssignConcat(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6246. {
  6247. ITypeInfo * targetType = target.queryType();
  6248. ICharsetInfo * targetCharset = targetType->queryCharset();
  6249. type_t ttc = targetType->getTypeCode();
  6250. switch (ttc)
  6251. {
  6252. case type_unicode:
  6253. case type_varunicode:
  6254. case type_utf8:
  6255. break;
  6256. case type_string:
  6257. case type_varstring:
  6258. case type_data:
  6259. if (!queryDefaultTranslation(targetCharset, expr->queryType()->queryCharset()))
  6260. break;
  6261. //fallthrough
  6262. default:
  6263. doBuildExprAssign(ctx, target, expr);
  6264. return;
  6265. }
  6266. HqlExprArray values;
  6267. expr->unwindList(values, no_concat);
  6268. //Combine adjacent constants (not folded previously because of the tree structure)
  6269. //Not optimized in the folder since it can mess up cse evaluation
  6270. for (unsigned i=0; i < values.ordinality()-1; i++)
  6271. {
  6272. IValue * firstValue = values.item(i).queryValue();
  6273. if (firstValue)
  6274. {
  6275. Linked<IValue> combinedValue = firstValue;
  6276. while (i+1 < values.ordinality())
  6277. {
  6278. IValue * nextValue = values.item(i+1).queryValue();
  6279. if (!nextValue)
  6280. break;
  6281. combinedValue.setown(concatValues(combinedValue, nextValue));
  6282. values.remove(i+1);
  6283. }
  6284. if (combinedValue->queryType()->getStringLen() == 0)
  6285. {
  6286. values.remove(i);
  6287. i--; // not nice, but will be incremented before comparison so safe
  6288. }
  6289. else if (combinedValue != firstValue)
  6290. values.replace(*createConstant(combinedValue.getClear()), i);
  6291. }
  6292. }
  6293. if (!target.isFixedSize())
  6294. {
  6295. doBuildVarLengthConcatF(ctx, target, values);
  6296. }
  6297. else if (!doBuildFixedLengthConcatF(ctx, target, values))
  6298. {
  6299. Owned<ITypeInfo> varType = getStretchedType(UNKNOWN_LENGTH, targetType);
  6300. OwnedHqlExpr castValue = createValue(no_concat, LINK(varType), values);
  6301. doBuildExprAssign(ctx, target, castValue);
  6302. }
  6303. }
  6304. //---------------------------------------------------------------------------
  6305. //-- no_div --
  6306. // also used for no_modulus
  6307. void HqlCppTranslator::doBuildExprDivide(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6308. {
  6309. if (expr->queryType()->getTypeCode() == type_decimal)
  6310. {
  6311. doBuildExprArith(ctx, expr, tgt);
  6312. return;
  6313. }
  6314. IHqlExpression * left = expr->queryChild(0);
  6315. IHqlExpression * right = expr->queryChild(1);
  6316. assertex(left->queryType() == right->queryType());
  6317. IValue * value = right->queryValue();
  6318. if (value)
  6319. {
  6320. Owned<IValue> zero = right->queryType()->castFrom(false, 0);
  6321. int cmp = value->compare(zero);
  6322. if (cmp == 0)
  6323. tgt.expr.setown(createConstant(zero.getClear()));
  6324. else
  6325. doBuildPureSubExpr(ctx, expr, tgt);
  6326. }
  6327. else
  6328. {
  6329. buildTempExpr(ctx, expr, tgt);
  6330. }
  6331. }
  6332. void HqlCppTranslator::doBuildAssignDivide(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6333. {
  6334. if (expr->queryType()->getTypeCode() == type_decimal)
  6335. {
  6336. doBuildExprAssign(ctx, target, expr);
  6337. return;
  6338. }
  6339. IHqlExpression * left = expr->queryChild(0);
  6340. IHqlExpression * right = expr->queryChild(1);
  6341. assertex(left->queryType() == right->queryType());
  6342. CHqlBoundExpr lhs,rhs;
  6343. buildExpr(ctx, left, lhs);
  6344. buildSimpleExpr(ctx, right, rhs);
  6345. IHqlExpression * divisor = rhs.expr.get();
  6346. OwnedHqlExpr pureExpr = createValue(expr->getOperator(), left->getType(), lhs.expr.getClear(), LINK(divisor));
  6347. IValue * zero = pureExpr->queryType()->castFrom(false, 0);
  6348. OwnedHqlExpr eZero = createConstant(zero);
  6349. IValue * value = rhs.expr->queryValue();
  6350. if (value)
  6351. {
  6352. int cmp = value->compare(eZero->queryValue());
  6353. if (cmp == 0)
  6354. assignBound(ctx, target, eZero);
  6355. else
  6356. assignBound(ctx, target, pureExpr);
  6357. }
  6358. else
  6359. {
  6360. BuildCtx subctx(ctx);
  6361. IHqlStmt * stmt = subctx.addFilter(divisor);
  6362. assignBound(subctx, target, pureExpr);
  6363. subctx.selectElse(stmt);
  6364. assignBound(subctx, target, eZero);
  6365. }
  6366. }
  6367. //---------------------------------------------------------------------------
  6368. //-- no_if --
  6369. bool HqlCppTranslator::ifRequiresAssignment(BuildCtx & ctx, IHqlExpression * expr)
  6370. {
  6371. IHqlExpression * trueExpr = expr->queryChild(1);
  6372. IHqlExpression * falseExpr = expr->queryChild(2);
  6373. if (requiresTemp(ctx, trueExpr, true) || requiresTemp(ctx, falseExpr, true) || expr->queryType()->getSize() == UNKNOWN_LENGTH)
  6374. return true;
  6375. if (trueExpr->queryType() != falseExpr->queryType() && isStringType(expr->queryType()))
  6376. return true;
  6377. if (expr->queryType()->getTypeCode() == type_decimal)
  6378. return true;
  6379. return false;
  6380. }
  6381. void HqlCppTranslator::doBuildAssignIf(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6382. {
  6383. if (!ifRequiresAssignment(ctx, expr))
  6384. {
  6385. doBuildExprAssign(ctx, target, expr);
  6386. return;
  6387. }
  6388. IHqlExpression * trueExpr = expr->queryChild(1);
  6389. IHqlExpression * falseExpr = expr->queryChild(2);
  6390. BuildCtx subctx(ctx);
  6391. CHqlBoundExpr cond;
  6392. buildCachedExpr(subctx, expr->queryChild(0), cond);
  6393. IHqlStmt * test = subctx.addFilter(cond.expr);
  6394. buildExprAssign(subctx, target, trueExpr);
  6395. subctx.selectElse(test);
  6396. buildExprAssign(subctx, target, falseExpr);
  6397. }
  6398. void HqlCppTranslator::doBuildExprIf(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6399. {
  6400. if (ifRequiresAssignment(ctx, expr))
  6401. {
  6402. buildTempExpr(ctx, expr, tgt);
  6403. return;
  6404. }
  6405. IHqlExpression * trueExpr = expr->queryChild(1);
  6406. IHqlExpression * falseExpr = expr->queryChild(2);
  6407. //Length should not be conditional...
  6408. CHqlBoundExpr cond;
  6409. CHqlBoundExpr boundTrue;
  6410. CHqlBoundExpr boundFalse;
  6411. buildCachedExpr(ctx, expr->queryChild(0), cond);
  6412. buildCachedExpr(ctx, trueExpr, boundTrue);
  6413. buildCachedExpr(ctx, falseExpr, boundFalse);
  6414. //true and false should have same type...
  6415. tgt.expr.setown(createValue(no_if, expr->getType(), cond.expr.getClear(), boundTrue.expr.getClear(), boundFalse.expr.getClear()));
  6416. }
  6417. void HqlCppTranslator::doBuildStmtIf(BuildCtx & ctx, IHqlExpression * expr)
  6418. {
  6419. BuildCtx subctx(ctx);
  6420. CHqlBoundExpr cond;
  6421. buildCachedExpr(subctx, expr->queryChild(0), cond);
  6422. IHqlStmt * test = subctx.addFilter(cond.expr);
  6423. buildStmt(subctx, expr->queryChild(1));
  6424. IHqlExpression * elseExpr = queryRealChild(expr, 2);
  6425. if (elseExpr && elseExpr->getOperator() != no_null)
  6426. {
  6427. subctx.selectElse(test);
  6428. buildStmt(subctx, elseExpr);
  6429. }
  6430. }
  6431. //---------------------------------------------------------------------------
  6432. //-- no_intformat --
  6433. IHqlExpression * HqlCppTranslator::createFormatCall(_ATOM func, IHqlExpression * expr)
  6434. {
  6435. HqlExprArray args;
  6436. unsigned max = expr->numChildren();
  6437. unsigned idx;
  6438. for (idx=0; idx < max; idx++)
  6439. {
  6440. IHqlExpression * cur = expr->queryChild(idx);;
  6441. args.append(*LINK(cur));
  6442. }
  6443. return bindFunctionCall(func, args);
  6444. }
  6445. void HqlCppTranslator::doBuildExprFormat(_ATOM func, BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6446. {
  6447. OwnedHqlExpr call = createFormatCall(func, expr);
  6448. buildExpr(ctx, call, tgt);
  6449. }
  6450. void HqlCppTranslator::doBuildAssignFormat(_ATOM func, BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6451. {
  6452. OwnedHqlExpr call = createFormatCall(func, expr);
  6453. buildExprAssign(ctx, target, call);
  6454. }
  6455. //---------------------------------------------------------------------------
  6456. void HqlCppTranslator::doBuildAssignToXml(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6457. {
  6458. IHqlExpression * row = expr->queryChild(0);
  6459. HqlExprArray args;
  6460. args.append(*buildMetaParameter(row));
  6461. args.append(*LINK(row));
  6462. args.append(*getSizetConstant(XWFtrim|XWFopt|XWFnoindent));
  6463. OwnedHqlExpr call = bindFunctionCall(ctxGetRowXmlAtom, args);
  6464. buildExprAssign(ctx, target, call);
  6465. }
  6466. //---------------------------------------------------------------------------
  6467. void HqlCppTranslator::processCppBodyDirectives(IHqlExpression * expr)
  6468. {
  6469. ForEachChild(i, expr)
  6470. {
  6471. IHqlExpression * cur = expr->queryChild(i);
  6472. if (cur->isAttribute())
  6473. {
  6474. _ATOM name = cur->queryName();
  6475. if (name == linkAtom)
  6476. {
  6477. //MORE: Add code to add the argument to the linker options.
  6478. }
  6479. else if (name == libraryAtom)
  6480. {
  6481. StringBuffer libraryName;
  6482. getStringValue(libraryName, cur->queryChild(0));
  6483. if (libraryName.length())
  6484. useLibrary(libraryName.str());
  6485. }
  6486. }
  6487. }
  6488. }
  6489. void HqlCppTranslator::doBuildExprCppBody(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr * tgt)
  6490. {
  6491. if (!allowEmbeddedCpp())
  6492. throwError(HQLERR_EmbeddedCppNotAllowed);
  6493. processCppBodyDirectives(expr);
  6494. StringBuffer text;
  6495. expr->queryChild(0)->queryValue()->getStringValue(text);
  6496. text.setLength(cleanupEmbeddedCpp(text.length(), (char*)text.str()));
  6497. OwnedHqlExpr quoted = createQuoted(text.str(), expr->getType());
  6498. if (tgt)
  6499. {
  6500. ITypeInfo * type = expr->queryType();
  6501. assertex(type->getTypeCode() == type_varstring || type->getSize() != UNKNOWN_LENGTH);
  6502. tgt->expr.set(quoted);
  6503. }
  6504. else
  6505. ctx.addExpr(quoted);
  6506. }
  6507. //---------------------------------------------------------------------------
  6508. //-- no_index --
  6509. IHqlExpression * getSimpleListIndex(BuildCtx & ctx, IHqlExpression * expr)
  6510. {
  6511. IHqlExpression * index = expr->queryChild(1);
  6512. if (!index->isConstant())
  6513. return NULL;
  6514. OwnedHqlExpr set = normalizeListCasts(expr->queryChild(0));
  6515. switch (set->getOperator())
  6516. {
  6517. case no_null:
  6518. case no_list:
  6519. break;
  6520. default:
  6521. return NULL;
  6522. }
  6523. OwnedHqlExpr folded = foldHqlExpression(index);
  6524. __int64 which = folded->queryValue()->getIntValue();
  6525. if ((which > 0) && (which <= set->numChildren()))
  6526. return LINK(set->queryChild((unsigned)which-1));
  6527. return createNullExpr(expr);
  6528. }
  6529. void HqlCppTranslator::doBuildExprIndex(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6530. {
  6531. OwnedHqlExpr simple = getSimpleListIndex(ctx, expr);
  6532. if (simple)
  6533. buildExpr(ctx, simple, tgt);
  6534. else
  6535. {
  6536. OwnedHqlExpr simpleList = simplifyFixedLengthList(expr->queryChild(0));
  6537. Owned<IHqlCppSetCursor> cursor = createSetSelector(ctx, simpleList);
  6538. cursor->buildExprSelect(ctx, expr, tgt);
  6539. }
  6540. }
  6541. void HqlCppTranslator::doBuildAssignIndex(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6542. {
  6543. OwnedHqlExpr simple = getSimpleListIndex(ctx, expr);
  6544. if (simple)
  6545. buildExprAssign(ctx, target, simple);
  6546. else
  6547. {
  6548. OwnedHqlExpr simpleList = simplifyFixedLengthList(expr->queryChild(0));
  6549. Owned<IHqlCppSetCursor> cursor = createSetSelector(ctx, simpleList);
  6550. cursor->buildAssignSelect(ctx, target, expr);
  6551. }
  6552. }
  6553. //---------------------------------------------------------------------------
  6554. //-- no_list --
  6555. bool isComplexSet(ITypeInfo * type, bool isConstant)
  6556. {
  6557. ITypeInfo * childType = type->queryChildType();
  6558. if (!childType)
  6559. return false;
  6560. switch (childType->getTypeCode())
  6561. {
  6562. case type_alien:
  6563. return true;
  6564. case type_string:
  6565. case type_qstring:
  6566. case type_data:
  6567. case type_unicode:
  6568. case type_varstring:
  6569. case type_varunicode:
  6570. return isUnknownSize(childType) && !isConstant;
  6571. case type_utf8:
  6572. case type_swapint:
  6573. case type_packedint:
  6574. return true;
  6575. case type_int:
  6576. switch (childType->getSize())
  6577. {
  6578. case 3: case 5: case 6: case 7:
  6579. return true;
  6580. }
  6581. return false;
  6582. }
  6583. return false;
  6584. }
  6585. bool isComplexSet(IHqlExpression * expr)
  6586. {
  6587. return isComplexSet(expr->queryType(), isConstantSet(expr));
  6588. }
  6589. bool isConstantSet(IHqlExpression * expr)
  6590. {
  6591. unsigned max = expr->numChildren();
  6592. unsigned idx;
  6593. for (idx = 0; idx < max; idx++)
  6594. {
  6595. IHqlExpression * child = expr->queryChild(idx);
  6596. if (!child->queryValue())
  6597. return false;
  6598. }
  6599. return true;
  6600. }
  6601. bool createUnknownLengthStringSet(MemoryBuffer & target, IHqlExpression * set)
  6602. {
  6603. ITypeInfo * elemType = set->queryType()->queryChildType();
  6604. type_t tc = elemType->getTypeCode();
  6605. ForEachChild(i, set)
  6606. {
  6607. IHqlExpression * cur = set->queryChild(i);
  6608. IValue * curValue = cur->queryValue();
  6609. if (!curValue)
  6610. return false;
  6611. size32_t sizeValue = curValue->getSize();
  6612. if ((tc != type_varstring) && (tc != type_varunicode))
  6613. {
  6614. size32_t lenValue = curValue->queryType()->getStringLen();
  6615. rtlWriteInt4(target.reserve(sizeof(size32_t)), lenValue);
  6616. }
  6617. curValue->toMem(target.reserve(sizeValue));
  6618. }
  6619. return true;
  6620. }
  6621. void HqlCppTranslator::doBuildExprConstList(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6622. {
  6623. BuildCtx declareCtx(*code, literalAtom);
  6624. if (!declareCtx.getMatchExpr(expr, tgt))
  6625. {
  6626. ITypeInfo * type = expr->queryType();
  6627. Linked<ITypeInfo> elementType = type->queryChildType();
  6628. if (!elementType)
  6629. throwError(HQLERR_NullSetCannotGenerate);
  6630. Owned<ITypeInfo> transferType;
  6631. OwnedHqlExpr table;
  6632. OwnedHqlExpr declare;
  6633. unsigned numElements = expr->numChildren();
  6634. LinkedHqlExpr values = expr;
  6635. if ((isTypePassedByAddress(elementType) && ((elementType->getTypeCode() != type_varstring) || isUnknownSize(elementType))))
  6636. {
  6637. if (isUnknownSize(elementType))
  6638. {
  6639. MemoryBuffer serialized;
  6640. bool ok = createUnknownLengthStringSet(serialized, values);
  6641. assertex(ok);
  6642. Owned<IValue> value = createDataValue(serialized.toByteArray(), serialized.length());
  6643. OwnedHqlExpr constValue = createConstant(LINK(value));
  6644. OwnedHqlExpr initializer = createValue(no_create_initializer, constValue->getType(), LINK(constValue));
  6645. Owned<ITypeInfo> declareType = makeConstantModifier(constValue->getType());
  6646. declare.setown(declareCtx.getTempDeclare(declareType, initializer));
  6647. ITypeInfo * arrayType = makeReferenceModifier(makeSetType(LINK(elementType)));
  6648. table.setown(createValue(no_typetransfer, arrayType, LINK(declare)));
  6649. tgt.length.setown(getSizetConstant(serialized.length()));
  6650. }
  6651. else if (elementType->isReference())
  6652. {
  6653. // use a var string type to get better C++ generated...
  6654. transferType.set(elementType);
  6655. elementType.setown(makeVarStringType(UNKNOWN_LENGTH));
  6656. }
  6657. else
  6658. {
  6659. // for string, data and qstring we need to initialize the array with a list of characters instead of
  6660. // a cstring e.g., char[][2] = { { 'a','b' }, { 'c', 'd' } };
  6661. HqlExprArray newValues;
  6662. ForEachChild(idx, expr)
  6663. {
  6664. IHqlExpression * next = expr->queryChild(idx);
  6665. newValues.append(*createValue(no_create_initializer, next->getType(), LINK(next)));
  6666. }
  6667. values.setown(createValue(no_list, makeSetType(LINK(elementType)), newValues));
  6668. }
  6669. }
  6670. if (!declare)
  6671. {
  6672. Owned<ITypeInfo> t = makeConstantModifier(makeArrayType(LINK(elementType), numElements));
  6673. declare.setown(declareCtx.getTempDeclare(t, values));
  6674. if (transferType)
  6675. {
  6676. ITypeInfo * arrayType = makeArrayType(LINK(transferType), numElements);
  6677. table.setown(createValue(no_typetransfer, arrayType, LINK(declare)));
  6678. }
  6679. }
  6680. tgt.count.setown(getSizetConstant(numElements));
  6681. tgt.expr.set(table ? table : declare);
  6682. //make sure tables get added before any global functions
  6683. declareCtx.associateExpr(expr, tgt);
  6684. if (options.spanMultipleCpp)
  6685. {
  6686. BuildCtx protoctx(*code, mainprototypesAtom);
  6687. protoctx.addDeclareExternal(declare);
  6688. }
  6689. }
  6690. }
  6691. void HqlCppTranslator::doBuildExprDynList(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6692. {
  6693. if (!ctx.getMatchExpr(expr, tgt))
  6694. {
  6695. ITypeInfo * type = expr->queryType();
  6696. ITypeInfo * elementType = type->queryChildType();
  6697. unsigned max = expr->numChildren();
  6698. //MORE: What if this is an array of variable length strings?
  6699. Owned<ITypeInfo> t = makeArrayType(LINK(elementType), max);
  6700. IHqlExpression * table = ctx.getTempDeclare(t, NULL);
  6701. // new code - should really use a selector...
  6702. unsigned idx;
  6703. CHqlBoundTarget boundTarget;
  6704. for (idx = 0; idx < max; idx++)
  6705. {
  6706. IHqlExpression * child = expr->queryChild(idx);
  6707. boundTarget.expr.setown(createValue(no_index, LINK(elementType), LINK(table), createConstant((int)idx)));
  6708. buildExprAssign(ctx, boundTarget, child);
  6709. }
  6710. tgt.count.setown(getSizetConstant(max));
  6711. tgt.expr.setown(table);
  6712. ctx.associateExpr(expr, tgt);
  6713. }
  6714. }
  6715. void HqlCppTranslator::doBuildExprList(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6716. {
  6717. ITypeInfo * type = expr->queryType();
  6718. switch (type->getTypeCode())
  6719. {
  6720. case type_set:
  6721. case type_array:
  6722. {
  6723. LinkedHqlExpr values = expr;
  6724. ITypeInfo * childType = type->queryChildType();
  6725. //MORE: Also alien data types and other weird things...
  6726. //if (childType->getSize() == UNKNOWN_LENGTH)
  6727. if (expr->numChildren() == 0)
  6728. {
  6729. tgt.length.setown(getSizetConstant(0));
  6730. tgt.expr.setown(createValue(no_nullptr, makeReferenceModifier(LINK(type))));
  6731. return;
  6732. }
  6733. else if (isComplexSet(expr))
  6734. {
  6735. buildTempExpr(ctx, expr, tgt);
  6736. return;
  6737. }
  6738. if (isConstantSet(expr))
  6739. doBuildExprConstList(ctx, values, tgt);
  6740. else
  6741. doBuildExprDynList(ctx, values, tgt);
  6742. tgt.isAll.set(queryBoolExpr(false));
  6743. }
  6744. break;
  6745. default:
  6746. throw(!"This type of list not supported yet");
  6747. }
  6748. }
  6749. void HqlCppTranslator::doBuildAssignList(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * _expr)
  6750. {
  6751. OwnedHqlExpr expr = simplifyFixedLengthList(_expr);
  6752. node_operator op = expr->getOperator();
  6753. assertex(op == no_list);
  6754. ITypeInfo * type = expr->queryType();
  6755. switch (type->getTypeCode())
  6756. {
  6757. case type_set:
  6758. case type_array:
  6759. break;
  6760. default:
  6761. throw(!"This type of list not supported yet");
  6762. }
  6763. //This is an assignment, a non-constant set would end up creating two temporaries.
  6764. unsigned numItems = expr->numChildren();
  6765. if (((numItems > 0) && (numItems < 3)) || isComplexSet(expr) || !isConstantSet(expr))
  6766. {
  6767. Owned<IHqlCppSetBuilder> builder = createTempSetBuilder(target.queryType()->queryChildType(), target.isAll);
  6768. builder->buildDeclare(ctx);
  6769. buildSetAssign(ctx, builder, expr);
  6770. builder->buildFinish(ctx, target);
  6771. }
  6772. else if (numItems == 0)
  6773. {
  6774. CHqlBoundExpr temp;
  6775. buildExpr(ctx, expr, temp);
  6776. if (target.isAll)
  6777. {
  6778. if (temp.isAll)
  6779. ctx.addAssign(target.isAll, temp.isAll);
  6780. else
  6781. ctx.addAssign(target.isAll, queryBoolExpr(false));
  6782. }
  6783. ctx.addAssign(target.length, temp.length);
  6784. ctx.addAssign(target.expr, temp.expr);
  6785. }
  6786. else
  6787. {
  6788. OwnedHqlExpr cast = ensureExprType(expr, target.queryType());
  6789. OwnedHqlExpr simpleCast = simplifyFixedLengthList(cast);
  6790. // can do a direct assignment without any casts
  6791. doBuildExprAssign(ctx, target, simpleCast);
  6792. }
  6793. }
  6794. void HqlCppTranslator::doBuildExprAll(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6795. {
  6796. tgt.isAll.set(queryBoolExpr(true));
  6797. tgt.length.setown(getSizetConstant(0));
  6798. tgt.expr.setown(createQuoted("0", makeSetType(NULL)));
  6799. }
  6800. void HqlCppTranslator::doBuildAssignAll(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6801. {
  6802. CHqlBoundExpr temp;
  6803. buildExpr(ctx, expr, temp);
  6804. ctx.addAssign(target.isAll, temp.isAll);
  6805. ctx.addAssign(target.length, temp.length);
  6806. ctx.addAssign(target.expr, temp.expr);
  6807. }
  6808. //---------------------------------------------------------------------------
  6809. //-- no_not --
  6810. void HqlCppTranslator::doBuildExprNot(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  6811. {
  6812. ITypeInfo * type = expr->queryChild(0)->queryType();
  6813. switch (type->getTypeCode())
  6814. {
  6815. case type_decimal:
  6816. {
  6817. //MORE: Could leak decimal stack.... Is the last line correct?
  6818. HqlExprArray args;
  6819. bindAndPush(ctx, expr->queryChild(0));
  6820. IHqlExpression * op = bindTranslatedFunctionCall(DecCompareNullAtom, args);
  6821. tgt.expr.setown(createValue(expr->getOperator(), LINK(boolType), op, getZero()));
  6822. }
  6823. break;
  6824. default:
  6825. doBuildPureSubExpr(ctx, expr, tgt);
  6826. break;
  6827. }
  6828. }
  6829. //---------------------------------------------------------------------------
  6830. //-- no_or --
  6831. IHqlExpression * HqlCppTranslator::convertOrToAnd(IHqlExpression * expr)
  6832. {
  6833. bool invert = true;
  6834. if (expr->getOperator() == no_not)
  6835. {
  6836. invert = false;
  6837. expr = expr->queryChild(0);
  6838. }
  6839. assertex(expr->getOperator() == no_or);
  6840. HqlExprArray original, inverted;
  6841. expr->unwindList(original, no_or);
  6842. ForEachItemIn(idx, original)
  6843. inverted.append(*getInverse(&original.item(idx)));
  6844. IHqlExpression * ret = createValue(no_and, makeBoolType(), inverted);
  6845. if (invert)
  6846. ret = createValue(no_not, makeBoolType(), ret);
  6847. return ret;
  6848. }
  6849. //---------------------------------------------------------------------------
  6850. // no_unicodeorder
  6851. void HqlCppTranslator::doBuildAssignUnicodeOrder(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  6852. {
  6853. CHqlBoundExpr lhs, rhs, locale, strength;
  6854. buildCachedExpr(ctx, expr->queryChild(0), lhs);
  6855. buildCachedExpr(ctx, expr->queryChild(1), rhs);
  6856. buildCachedExpr(ctx, expr->queryChild(2), locale);
  6857. buildCachedExpr(ctx, expr->queryChild(3), strength);
  6858. Owned<IHqlExpression> op;
  6859. HqlExprArray args;
  6860. ITypeInfo * realType = lhs.expr->queryType()->queryPromotedType();
  6861. switch(realType->getTypeCode())
  6862. {
  6863. case type_unicode:
  6864. args.append(*getBoundLength(lhs));
  6865. args.append(*getElementPointer(lhs.expr));
  6866. args.append(*getBoundLength(rhs));
  6867. args.append(*getElementPointer(rhs.expr));
  6868. args.append(*getElementPointer(locale.expr));
  6869. args.append(*strength.expr.getLink());
  6870. op.setown(bindTranslatedFunctionCall(compareUnicodeUnicodeStrengthAtom, args));
  6871. break;
  6872. case type_varunicode:
  6873. args.append(*getElementPointer(lhs.expr));
  6874. args.append(*getElementPointer(rhs.expr));
  6875. args.append(*getElementPointer(locale.expr));
  6876. args.append(*strength.expr.getLink());
  6877. op.setown(bindTranslatedFunctionCall(compareVUnicodeVUnicodeStrengthAtom, args));
  6878. break;
  6879. case type_utf8:
  6880. args.append(*getBoundLength(lhs));
  6881. args.append(*getElementPointer(lhs.expr));
  6882. args.append(*getBoundLength(rhs));
  6883. args.append(*getElementPointer(rhs.expr));
  6884. args.append(*getElementPointer(locale.expr));
  6885. args.append(*strength.expr.getLink());
  6886. op.setown(bindTranslatedFunctionCall(compareUtf8Utf8StrengthAtom, args));
  6887. break;
  6888. default:
  6889. UNIMPLEMENTED;
  6890. }
  6891. assignBound(ctx, target, op);
  6892. }
  6893. //---------------------------------------------------------------------------
  6894. //-- no_order --
  6895. static void buildIteratorFirst(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * iter, IHqlExpression * row)
  6896. {
  6897. StringBuffer s;
  6898. translator.generateExprCpp(s, row).append(" = (byte*)");
  6899. translator.generateExprCpp(s, iter).append(".first();");
  6900. ctx.addQuoted(s);
  6901. }
  6902. static void buildIteratorNext(HqlCppTranslator & translator, BuildCtx & ctx, IHqlExpression * iter, IHqlExpression * row)
  6903. {
  6904. StringBuffer s;
  6905. translator.generateExprCpp(s, row).append(" = (byte*)");
  6906. translator.generateExprCpp(s, iter).append(".next();");
  6907. ctx.addQuoted(s);
  6908. }
  6909. static void buildIteratorIsValid(BuildCtx & ctx, IHqlExpression * iter, IHqlExpression * row, CHqlBoundExpr & bound)
  6910. {
  6911. bound.expr.set(row);
  6912. }
  6913. void HqlCppTranslator::doBuildAssignCompareRow(BuildCtx & ctx, EvaluateCompareInfo & info, IHqlExpression * left, IHqlExpression * right)
  6914. {
  6915. HqlExprArray leftValues, rightValues;
  6916. IHqlExpression * record = left->queryRecord();
  6917. expandRowOrder(left->queryNormalizedSelector(), record, leftValues, false);
  6918. expandRowOrder(right->queryNormalizedSelector(), record, rightValues, false);
  6919. optimizeOrderValues(leftValues, rightValues, false);
  6920. doBuildAssignCompare(ctx, info, leftValues, rightValues, true, false); //MORE: ,no_break,true
  6921. }
  6922. void HqlCppTranslator::doBuildAssignCompareTable(BuildCtx & ctx, EvaluateCompareInfo & info, IHqlExpression * left, IHqlExpression * right)
  6923. {
  6924. ITypeInfo * targetType = info.target.queryType();
  6925. OwnedHqlExpr zeroTarget = createConstant(targetType->castFrom(true, 0));
  6926. OwnedHqlExpr plusOne = createConstant(targetType->castFrom(true, +1));
  6927. OwnedHqlExpr minusOne = createConstant(targetType->castFrom(true, -1));
  6928. // cmp = 0;
  6929. assignBound(ctx, info.target, zeroTarget);
  6930. BuildCtx subctx(ctx);
  6931. subctx.addGroup(); // stop bound cursors leaking outside the testing block.
  6932. // i1 iter1; i1.first();
  6933. HqlExprAttr leftIter, leftRow;
  6934. Owned<IHqlCppDatasetCursor> cursor = createDatasetSelector(subctx, left);
  6935. cursor->buildIterateClass(subctx, leftIter, leftRow);
  6936. buildIteratorFirst(*this, subctx, leftIter, leftRow);
  6937. // i2; forEachIn(i2); {
  6938. CHqlBoundExpr isValid;
  6939. BuildCtx loopctx(subctx);
  6940. buildDatasetIterate(loopctx, right, true);
  6941. bindTableCursor(loopctx, left, leftRow);
  6942. // if (!i1.isValid()) { cmp = -1; break; }
  6943. buildIteratorIsValid(loopctx, leftIter, leftRow, isValid);
  6944. OwnedHqlExpr test = createValue(no_not, makeBoolType(), isValid.expr.getClear());
  6945. BuildCtx moreRightCtx(loopctx);
  6946. moreRightCtx.addFilter(test);
  6947. if (info.actionIfDiffer == return_stmt)
  6948. {
  6949. if (info.isEqualityCompare())
  6950. {
  6951. OwnedHqlExpr returnValue = info.getEqualityReturnValue();
  6952. moreRightCtx.addReturn(returnValue);
  6953. }
  6954. else
  6955. moreRightCtx.addReturn(minusOne);
  6956. }
  6957. else
  6958. {
  6959. buildExprAssign(moreRightCtx, info.target, minusOne);
  6960. moreRightCtx.addBreak();
  6961. }
  6962. //Now do the comparison....
  6963. {
  6964. EvaluateCompareInfo childInfo(info);
  6965. if (childInfo.actionIfDiffer == break_stmt)
  6966. childInfo.actionIfDiffer = null_stmt;
  6967. //***childInfo??
  6968. doBuildAssignCompareRow(loopctx, info, left, right);
  6969. }
  6970. if (info.actionIfDiffer != return_stmt)
  6971. {
  6972. // if (cmp != 0) break;
  6973. BuildCtx donectx(loopctx);
  6974. donectx.addFilter(info.target.expr);
  6975. donectx.addQuoted("break;");
  6976. }
  6977. // i1.next();
  6978. buildIteratorNext(*this, loopctx, leftIter, leftRow);
  6979. buildIteratorIsValid(subctx, leftIter, leftRow, isValid);
  6980. if (info.actionIfDiffer == return_stmt)
  6981. {
  6982. //if (i1.isValid) return +1;
  6983. BuildCtx moreLeftCtx(subctx);
  6984. moreLeftCtx.addFilter(isValid.expr);
  6985. if (info.isEqualityCompare())
  6986. {
  6987. OwnedHqlExpr returnValue = info.getEqualityReturnValue();
  6988. moreLeftCtx.addReturn(returnValue);
  6989. }
  6990. else
  6991. moreLeftCtx.addReturn(plusOne);
  6992. }
  6993. else
  6994. {
  6995. //if (cmp == 0 && i1.isValid) cmp = +1;
  6996. OwnedHqlExpr cmp = createBoolExpr(no_and, createBoolExpr(no_eq, LINK(info.target.expr), LINK(zeroTarget)), LINK(isValid.expr));
  6997. BuildCtx moreLeftCtx(subctx);
  6998. moreLeftCtx.addFilter(cmp);
  6999. buildExprAssign(moreLeftCtx, info.target, plusOne);
  7000. BuildCtx tailctx(ctx);
  7001. if (info.actionIfDiffer == break_stmt)
  7002. {
  7003. tailctx.addFilter(info.target.expr);
  7004. tailctx.addBreak();
  7005. }
  7006. }
  7007. }
  7008. void HqlCppTranslator::expandRowOrder(IHqlExpression * selector, IHqlExpression * record, HqlExprArray & values, bool isRow)
  7009. {
  7010. ForEachChild(idx, record)
  7011. {
  7012. IHqlExpression * field = record->queryChild(idx);
  7013. switch (field->getOperator())
  7014. {
  7015. case no_ifblock:
  7016. expandRowOrder(selector, field->queryChild(1), values, isRow);
  7017. break;
  7018. case no_record:
  7019. expandRowOrder(selector, field, values, isRow);
  7020. break;
  7021. case no_field:
  7022. {
  7023. OwnedHqlExpr selected;
  7024. if (isRow)
  7025. selected.setown(createNewSelectExpr(LINK(selector), LINK(field)));
  7026. else
  7027. selected.setown(createSelectExpr(LINK(selector), LINK(field)));
  7028. if (field->isDatarow())
  7029. expandRowOrder(selected, field->queryRecord(), values, false);
  7030. else
  7031. values.append(*LINK(selected));
  7032. break;
  7033. }
  7034. }
  7035. }
  7036. }
  7037. void HqlCppTranslator::expandSimpleOrder(IHqlExpression * left, IHqlExpression * right, HqlExprArray & leftValues, HqlExprArray & rightValues)
  7038. {
  7039. while ((left->getOperator() == no_negate) && (right->getOperator() == no_negate))
  7040. {
  7041. IHqlExpression * temp = right->queryChild(0);
  7042. right = left->queryChild(0);
  7043. left = temp;
  7044. }
  7045. if (left == right)
  7046. {
  7047. //Weird code is here just so I can force some strange exceptions in the regression suite.
  7048. IHqlExpression * cur = left;
  7049. if (cur->getOperator() == no_alias)
  7050. cur = cur->queryChild(0);
  7051. if (cur->getOperator() != no_nofold)
  7052. return;
  7053. }
  7054. if (left->isDatarow())
  7055. {
  7056. IHqlExpression * record = left->queryRecord();
  7057. assertex(right->isDatarow() && (record == right->queryRecord()));
  7058. expandRowOrder(left, record, leftValues, !isActiveRow(left));
  7059. expandRowOrder(right, record, rightValues, !isActiveRow(right));
  7060. }
  7061. else
  7062. {
  7063. leftValues.append(*LINK(left));
  7064. rightValues.append(*LINK(right));
  7065. }
  7066. }
  7067. void HqlCppTranslator::expandOrder(IHqlExpression * expr, HqlExprArray & leftValues, HqlExprArray & rightValues, SharedHqlExpr & defaultValue)
  7068. {
  7069. OwnedHqlExpr left = normalizeListCasts(expr->queryChild(0));
  7070. OwnedHqlExpr right = normalizeListCasts(expr->queryChild(1));
  7071. if ((isFixedLengthList(left) || isNullList(left)) && (isFixedLengthList(right) || isNullList(right)))
  7072. {
  7073. unsigned maxLeft = left->numChildren();
  7074. unsigned maxRight = right->numChildren();
  7075. unsigned max = std::min(maxLeft, maxRight);
  7076. for (unsigned i=0; i < max; i++)
  7077. expandSimpleOrder(left->queryChild(i), right->queryChild(i), leftValues, rightValues);
  7078. if (maxLeft != maxRight)
  7079. defaultValue.setown(createConstant(signedType->castFrom(true, ((maxLeft > maxRight) ? +1 : -1))));
  7080. }
  7081. else
  7082. expandSimpleOrder(left, right, leftValues, rightValues);
  7083. }
  7084. IHqlExpression * HqlCppTranslator::querySimpleOrderSelector(IHqlExpression * expr)
  7085. {
  7086. if (expr->getOperator() != no_select)
  7087. return NULL;
  7088. return queryDatasetCursor(expr);
  7089. }
  7090. static unsigned getMemcmpSize(IHqlExpression * left, IHqlExpression * right, bool isEqualityCompare)
  7091. {
  7092. ITypeInfo * leftType = left->queryType();
  7093. if (!leftType)
  7094. return 0;
  7095. if (!isSameBasicType(leftType, right->queryType()))
  7096. return 0;
  7097. unsigned size = leftType->getSize();
  7098. switch (leftType->getTypeCode())
  7099. {
  7100. case type_bigendianint:
  7101. case type_boolean:
  7102. return size;
  7103. case type_littleendianint:
  7104. if ((size == 1) && !leftType->isSigned())
  7105. return 1;
  7106. if (isEqualityCompare)
  7107. return size;
  7108. break;
  7109. case type_string:
  7110. case type_data:
  7111. case type_qstring:
  7112. if (size != UNKNOWN_LENGTH)
  7113. return size;
  7114. break;
  7115. }
  7116. return 0;
  7117. }
  7118. void HqlCppTranslator::optimizeOrderValues(HqlExprArray & leftValues, HqlExprArray & rightValues, bool isEqualityCompare)
  7119. {
  7120. unsigned max = leftValues.ordinality();
  7121. if (max <= 1)
  7122. return;
  7123. for (unsigned i=0; i < max-1; i++)
  7124. {
  7125. IHqlExpression * curFirstLeft = &leftValues.item(i);
  7126. IHqlExpression * curFirstRight = &rightValues.item(i);
  7127. IHqlExpression * leftSel = querySimpleOrderSelector(curFirstLeft);
  7128. IHqlExpression * rightSel = querySimpleOrderSelector(curFirstRight);
  7129. if (!leftSel || !rightSel)
  7130. continue;
  7131. unsigned compareSize = getMemcmpSize(curFirstLeft, curFirstRight, isEqualityCompare);
  7132. if (!compareSize)
  7133. continue;
  7134. IHqlExpression * nextLeft = &leftValues.item(i+1);
  7135. IHqlExpression * nextRight = &rightValues.item(i+1);
  7136. if (querySimpleOrderSelector(nextLeft) != leftSel || querySimpleOrderSelector(nextRight) != rightSel ||
  7137. (getMemcmpSize(nextLeft, nextRight, isEqualityCompare) == 0))
  7138. continue;
  7139. //Worth iterating the selectors...
  7140. RecordSelectIterator leftIter(leftSel->queryRecord(), leftSel);
  7141. ForEach(leftIter)
  7142. if (leftIter.query() == curFirstLeft)
  7143. break;
  7144. if (!leftIter.isValid() || leftIter.isInsideIfBlock())
  7145. continue;
  7146. RecordSelectIterator rightIter(rightSel->queryRecord(), rightSel);
  7147. ForEach(rightIter)
  7148. if (rightIter.query() == curFirstRight)
  7149. break;
  7150. if (!rightIter.isValid() || rightIter.isInsideIfBlock())
  7151. continue;
  7152. unsigned j; // linux wants it declared outside of 'for'
  7153. for (j=i+1; j < max; j++)
  7154. {
  7155. if (!leftIter.next() || leftIter.isInsideIfBlock())
  7156. break;
  7157. if (!rightIter.next() || rightIter.isInsideIfBlock())
  7158. break;
  7159. IHqlExpression * nextLeft = &leftValues.item(j);
  7160. IHqlExpression * nextRight = &rightValues.item(j);
  7161. if (leftIter.query() != nextLeft || rightIter.query() != nextRight)
  7162. break;
  7163. unsigned thisSize = getMemcmpSize(nextLeft, nextRight, isEqualityCompare);
  7164. if (!thisSize)
  7165. break;
  7166. compareSize += thisSize;
  7167. }
  7168. if (j != i+1)
  7169. {
  7170. IHqlExpression * newLeft = createValue(no_typetransfer, makeStringType(compareSize), LINK(curFirstLeft));
  7171. IHqlExpression * newRight = createValue(no_typetransfer, makeStringType(compareSize), LINK(curFirstRight));
  7172. leftValues.replace(*newLeft, i);
  7173. rightValues.replace(*newRight, i);
  7174. leftValues.removen(i+1, j-(i+1));
  7175. rightValues.removen(i+1, j-(i+1));
  7176. max -= (j - (i+1));
  7177. }
  7178. }
  7179. }
  7180. inline IHqlExpression * createSignedConstant(__int64 value)
  7181. {
  7182. return createConstant(signedType->castFrom(true, value));
  7183. }
  7184. static IHqlExpression * convertAllToInteger(IHqlExpression * allExpr)
  7185. {
  7186. IValue * allValue = allExpr->queryValue();
  7187. if (allValue)
  7188. return createSignedConstant(allValue->getBoolValue() ? 1 : 0);
  7189. return createValue(no_if, LINK(signedType), LINK(allExpr), createSignedConstant(1), createSignedConstant(0));
  7190. }
  7191. void HqlCppTranslator::doBuildAssignCompareElement(BuildCtx & ctx, EvaluateCompareInfo & info, IHqlExpression * left, IHqlExpression * right, bool isFirst, bool isLast)
  7192. {
  7193. if (left->getOperator() == no_if && right->getOperator() == no_if && left->queryChild(0) == right->queryChild(0))
  7194. {
  7195. BuildCtx subctx(ctx);
  7196. IHqlStmt * filter = buildFilterViaExpr(subctx, left->queryChild(0));
  7197. doBuildAssignCompareElement(subctx, info, left->queryChild(1), right->queryChild(1), isFirst, false);
  7198. if ((isFirst && (info.actionIfDiffer != return_stmt)) || left->queryChild(2) != right->queryChild(2))
  7199. {
  7200. subctx.selectElse(filter);
  7201. doBuildAssignCompareElement(subctx, info, left->queryChild(2), right->queryChild(2), isFirst, false);
  7202. }
  7203. return;
  7204. }
  7205. if (left == right)
  7206. {
  7207. //Can happen from conditions expanded above
  7208. if (isFirst)
  7209. {
  7210. if (info.actionIfDiffer != return_stmt)
  7211. buildExprAssign(ctx, info.target, queryZero());
  7212. }
  7213. return;
  7214. }
  7215. ITypeInfo * leftType = left->queryType();
  7216. type_t tc;
  7217. if (leftType)
  7218. tc = leftType->getTypeCode();
  7219. else
  7220. tc = type_set;
  7221. CHqlBoundExpr lhs,rhs;
  7222. bool useMemCmp = false;
  7223. switch (tc)
  7224. {
  7225. case type_table:
  7226. case type_groupedtable:
  7227. doBuildAssignCompareTable(ctx, info, left, right);
  7228. return;
  7229. case type_row:
  7230. doBuildAssignCompareRow(ctx, info, left, right);
  7231. return;
  7232. case type_bigendianint:
  7233. {
  7234. //MORE: Compare big endian integers with a memcmp
  7235. if (hasAddress(ctx, left) && hasAddress(ctx, right) && isSameBasicType(leftType, right->queryType()))
  7236. {
  7237. buildAddress(ctx, left, lhs);
  7238. buildAddress(ctx, right, rhs);
  7239. useMemCmp = true;
  7240. break;
  7241. }
  7242. Owned<ITypeInfo> type = makeIntType(leftType->getSize(), leftType->isSigned());
  7243. OwnedHqlExpr intLeft = createValue(no_implicitcast, type.getLink(), LINK(left));
  7244. OwnedHqlExpr intRight = createValue(no_implicitcast, type.getLink(), LINK(right));
  7245. buildCachedExpr(ctx, intLeft, lhs);
  7246. buildCachedExpr(ctx, intRight, rhs);
  7247. break;
  7248. }
  7249. case type_string:
  7250. case type_data:
  7251. case type_qstring:
  7252. {
  7253. OwnedHqlExpr simpleLeft = getSimplifyCompareArg(left);
  7254. OwnedHqlExpr simpleRight = getSimplifyCompareArg(right);
  7255. buildCachedExpr(ctx, simpleLeft, lhs);
  7256. buildCachedExpr(ctx, simpleRight, rhs);
  7257. break;
  7258. }
  7259. default:
  7260. buildCachedExpr(ctx, left, lhs);
  7261. buildCachedExpr(ctx, right, rhs);
  7262. break;
  7263. }
  7264. ITypeInfo * realType = realType = lhs.queryType()->queryPromotedType();
  7265. tc = realType->getTypeCode();
  7266. IHqlExpression * op = NULL;
  7267. switch (tc)
  7268. {
  7269. //MORE: Should common up with comparison code...
  7270. case type_string:
  7271. case type_data:
  7272. case type_qstring:
  7273. {
  7274. HqlExprArray args;
  7275. _ATOM func;
  7276. if (lhs.length || rhs.length || needVarStringCompare(realType, rhs.queryType()->queryPromotedType()))
  7277. {
  7278. //MORE: This does not cope with different padding characters...
  7279. func = queryStrCompareFunc(realType);
  7280. args.append(*getBoundLength(lhs));
  7281. args.append(*getElementPointer(lhs.expr));
  7282. args.append(*getBoundLength(rhs));
  7283. args.append(*getElementPointer(rhs.expr));
  7284. }
  7285. else
  7286. {
  7287. func = memcmpAtom;
  7288. args.append(*getElementPointer(lhs.expr));
  7289. args.append(*getElementPointer(rhs.expr));
  7290. args.append(*getSizetConstant(realType->getSize()));
  7291. }
  7292. op = bindTranslatedFunctionCall(func, args);
  7293. break;
  7294. }
  7295. case type_unicode:
  7296. {
  7297. HqlExprArray args;
  7298. assertex(haveCommonLocale(leftType, right->queryType()));
  7299. char const * locale = getCommonLocale(leftType, right->queryType())->str();
  7300. args.append(*getBoundLength(lhs));
  7301. args.append(*getElementPointer(lhs.expr));
  7302. args.append(*getBoundLength(rhs));
  7303. args.append(*getElementPointer(rhs.expr));
  7304. args.append(*createConstant(locale));
  7305. op = bindTranslatedFunctionCall(compareUnicodeUnicodeAtom, args);
  7306. break;
  7307. }
  7308. case type_varunicode:
  7309. {
  7310. HqlExprArray args;
  7311. assertex(haveCommonLocale(leftType, right->queryType()));
  7312. char const * locale = getCommonLocale(leftType, right->queryType())->str();
  7313. args.append(*getElementPointer(lhs.expr));
  7314. args.append(*getElementPointer(rhs.expr));
  7315. args.append(*createConstant(locale));
  7316. op = bindTranslatedFunctionCall(compareVUnicodeVUnicodeAtom, args);
  7317. break;
  7318. }
  7319. case type_utf8:
  7320. {
  7321. HqlExprArray args;
  7322. assertex(haveCommonLocale(leftType, right->queryType()));
  7323. char const * locale = getCommonLocale(leftType, right->queryType())->str();
  7324. args.append(*getBoundLength(lhs));
  7325. args.append(*getElementPointer(lhs.expr));
  7326. args.append(*getBoundLength(rhs));
  7327. args.append(*getElementPointer(rhs.expr));
  7328. args.append(*createConstant(locale));
  7329. op = bindTranslatedFunctionCall(compareUtf8Utf8Atom, args);
  7330. break;
  7331. }
  7332. case type_varstring:
  7333. {
  7334. HqlExprArray args;
  7335. args.append(*getElementPointer(lhs.expr));
  7336. args.append(*getElementPointer(rhs.expr));
  7337. op = bindTranslatedFunctionCall(compareVStrVStrAtom, args);
  7338. break;
  7339. }
  7340. case type_decimal:
  7341. {
  7342. HqlExprArray args;
  7343. if (!isPushed(lhs) && !isPushed(rhs) && (leftType->queryPromotedType() == right->queryType()->queryPromotedType()))
  7344. {
  7345. args.append(*getSizetConstant(leftType->queryPromotedType()->getSize()));
  7346. args.append(*getPointer(lhs.expr));
  7347. args.append(*getPointer(rhs.expr));
  7348. op = bindTranslatedFunctionCall(leftType->isSigned() ? DecCompareDecimalAtom : DecCompareUDecimalAtom, args);
  7349. }
  7350. else
  7351. {
  7352. bool pushedLhs = ensurePushed(ctx, lhs);
  7353. bool pushedRhs = ensurePushed(ctx, rhs);
  7354. //NB: Arguments could be pushed in opposite order 1 <=> x *2
  7355. if (pushedLhs && !pushedRhs)
  7356. op = bindTranslatedFunctionCall(DecDistinctRAtom, args);
  7357. else
  7358. op = bindTranslatedFunctionCall(DecDistinctAtom, args);
  7359. }
  7360. break;
  7361. }
  7362. case type_set:
  7363. case type_array:
  7364. {
  7365. //compare all
  7366. OwnedHqlExpr leftAll = lhs.getIsAll();
  7367. OwnedHqlExpr rightAll = rhs.getIsAll();
  7368. assertex(leftAll && rightAll);
  7369. if (leftAll != rightAll)
  7370. {
  7371. if (leftAll->queryValue() && rightAll->queryValue())
  7372. {
  7373. op = createConstant(leftAll->queryValue()->getIntValue() - rightAll->queryValue()->getIntValue());
  7374. break;
  7375. }
  7376. if (getIntValue(leftAll, false) || getIntValue(rightAll, false))
  7377. {
  7378. op = createValue(no_sub, LINK(signedType), convertAllToInteger(leftAll), convertAllToInteger(rightAll));
  7379. break;
  7380. }
  7381. }
  7382. if (lhs.expr != rhs.expr)
  7383. {
  7384. HqlExprArray args;
  7385. args.append(*getBoundLength(lhs));
  7386. args.append(*getElementPointer(lhs.expr));
  7387. args.append(*getBoundLength(rhs));
  7388. args.append(*getElementPointer(rhs.expr));
  7389. op = bindTranslatedFunctionCall(compareDataDataAtom, args);
  7390. }
  7391. if (leftAll != rightAll)
  7392. {
  7393. IHqlExpression * orderAll = createValue(no_sub, LINK(signedType), convertAllToInteger(leftAll), convertAllToInteger(rightAll));
  7394. if (op)
  7395. {
  7396. IHqlExpression * cond = NULL;
  7397. if (!getIntValue(leftAll, true))
  7398. {
  7399. if (!getIntValue(rightAll, true))
  7400. cond = NULL;
  7401. else
  7402. cond = LINK(rightAll);
  7403. }
  7404. else
  7405. {
  7406. if (!getIntValue(rightAll, true))
  7407. cond = LINK(leftAll);
  7408. else
  7409. cond = createBoolExpr(no_or, LINK(leftAll), LINK(rightAll));
  7410. }
  7411. if (cond)
  7412. op = createValue(no_if, LINK(signedType), cond, orderAll, op);
  7413. else
  7414. orderAll->Release();
  7415. }
  7416. else
  7417. op = orderAll;
  7418. }
  7419. if (!op)
  7420. op = getZero();
  7421. break;
  7422. }
  7423. case type_boolean:
  7424. case type_swapint:
  7425. case type_packedint:
  7426. case type_int:
  7427. if (!useMemCmp && !info.isEqualityCompare() && (realType->getSize() < signedType->getSize()))
  7428. {
  7429. op = createValue(no_sub, LINK(signedType),
  7430. createValue(no_implicitcast, LINK(signedType), lhs.expr.getLink()),
  7431. createValue(no_implicitcast, LINK(signedType), rhs.expr.getLink()));
  7432. break;
  7433. }
  7434. //fall through
  7435. default:
  7436. if (useMemCmp)
  7437. {
  7438. HqlExprArray args;
  7439. args.append(*lhs.expr.getLink());
  7440. args.append(*rhs.expr.getLink());
  7441. args.append(*getSizetConstant(leftType->getSize()));
  7442. op = bindTranslatedFunctionCall(memcmpAtom, args);
  7443. }
  7444. else
  7445. {
  7446. if (info.isEqualityCompare())
  7447. {
  7448. op = createBoolExpr(no_ne, LINK(lhs.expr), LINK(rhs.expr));
  7449. }
  7450. else
  7451. {
  7452. ensureSimpleExpr(ctx, lhs);
  7453. ensureSimpleExpr(ctx, rhs);
  7454. OwnedHqlExpr testlt = createBoolExpr(no_lt, lhs.expr.getLink(), rhs.expr.getLink());
  7455. OwnedHqlExpr retlt = createIntConstant(-1);
  7456. OwnedHqlExpr testgt = createBoolExpr(no_gt, lhs.expr.getLink(), rhs.expr.getLink());
  7457. OwnedHqlExpr retgt = createIntConstant(+1);
  7458. if (info.actionIfDiffer == return_stmt)
  7459. {
  7460. BuildCtx subctx1(ctx);
  7461. subctx1.addFilter(testlt);
  7462. subctx1.addReturn(retlt);
  7463. BuildCtx subctx2(ctx);
  7464. subctx2.addFilter(testgt);
  7465. subctx2.addReturn(retgt);
  7466. return;
  7467. }
  7468. else
  7469. {
  7470. // generate (a < b ? -1 : (a > b ? +1 : 0))
  7471. op = createValue(no_if, LINK(signedType),
  7472. LINK(testlt), LINK(retlt),
  7473. createValue(no_if, LINK(signedType), LINK(testgt), LINK(retgt), getZero()));
  7474. }
  7475. }
  7476. }
  7477. break;
  7478. }
  7479. OwnedHqlExpr safeReleaseOp = op;
  7480. assertex(op);
  7481. BuildCtx subctx(ctx);
  7482. if (info.isEqualityCompare() && (info.actionIfDiffer == return_stmt))
  7483. {
  7484. subctx.addFilter(op);
  7485. OwnedHqlExpr returnValue = info.getEqualityReturnValue();
  7486. subctx.addReturn(returnValue);
  7487. }
  7488. else
  7489. {
  7490. assignBound(subctx, info.target, op);
  7491. switch (info.actionIfDiffer)
  7492. {
  7493. case break_stmt:
  7494. subctx.addFilter(info.target.expr);
  7495. subctx.addBreak();
  7496. break;
  7497. case return_stmt:
  7498. if (!isLast || info.hasDefault)
  7499. subctx.addFilter(info.target.expr);
  7500. else
  7501. info.alwaysReturns = true;
  7502. subctx.addReturn(info.target.expr);
  7503. break;
  7504. }
  7505. }
  7506. }
  7507. void HqlCppTranslator::doBuildAssignCompare(BuildCtx & ctx, EvaluateCompareInfo & info, HqlExprArray & leftValues, HqlExprArray & rightValues, bool isFirst, bool isOuter)
  7508. {
  7509. assertex(leftValues.ordinality() == rightValues.ordinality());
  7510. Owned<BuildCtx> subctx = new BuildCtx(ctx);
  7511. OwnedHqlExpr compare = createBoolExpr(no_not, LINK(info.target.expr));
  7512. unsigned idx;
  7513. unsigned max = leftValues.ordinality();
  7514. for (idx = 0; idx < max; idx++)
  7515. {
  7516. if ((idx & 7) == 0)
  7517. subctx.setown(new BuildCtx(ctx));
  7518. if (!info.actionIfDiffer && !isFirst)
  7519. subctx->addFilter(compare);
  7520. doBuildAssignCompareElement(*subctx, info, &leftValues.item(idx), &rightValues.item(idx), isFirst, isOuter && (idx == max-1));
  7521. isFirst = false;
  7522. }
  7523. }
  7524. void HqlCppTranslator::doBuildAssignOrder(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  7525. {
  7526. HqlExprArray leftValues, rightValues;
  7527. OwnedHqlExpr defaultValue;
  7528. expandOrder(expr, leftValues, rightValues, defaultValue);
  7529. optimizeOrderValues(leftValues, rightValues, false);
  7530. EvaluateCompareInfo info(no_order);
  7531. info.target.set(target);
  7532. doBuildAssignCompare(ctx, info, leftValues, rightValues, true, false);
  7533. unsigned maxLeft = leftValues.ordinality();
  7534. if (defaultValue)
  7535. {
  7536. if (maxLeft != 0)
  7537. {
  7538. OwnedHqlExpr compare = createBoolExpr(no_not, LINK(target.expr));
  7539. ctx.addFilter(compare);
  7540. }
  7541. buildExprAssign(ctx, target, defaultValue);
  7542. }
  7543. else if (maxLeft == 0)
  7544. buildExprAssign(ctx, target, queryZero());
  7545. }
  7546. void HqlCppTranslator::doBuildReturnCompare(BuildCtx & ctx, IHqlExpression * expr, node_operator op, bool isBoolEquality)
  7547. {
  7548. HqlExprArray leftValues, rightValues;
  7549. OwnedHqlExpr defaultValue;
  7550. expandOrder(expr, leftValues, rightValues, defaultValue);
  7551. optimizeOrderValues(leftValues, rightValues, (op == no_eq));
  7552. EvaluateCompareInfo info(op);
  7553. info.actionIfDiffer = return_stmt;
  7554. info.isBoolEquality = isBoolEquality;
  7555. info.hasDefault = (defaultValue != NULL);
  7556. createTempFor(ctx, expr, info.target);
  7557. doBuildAssignCompare(ctx, info, leftValues, rightValues, true, true);
  7558. if (!info.alwaysReturns)
  7559. {
  7560. if (info.isBoolEquality)
  7561. {
  7562. OwnedHqlExpr returnValue = createConstant(defaultValue == NULL);
  7563. buildReturn(ctx, returnValue);
  7564. }
  7565. else
  7566. {
  7567. if (defaultValue)
  7568. buildReturn(ctx, defaultValue);
  7569. else
  7570. buildReturn(ctx, queryZero());
  7571. }
  7572. }
  7573. }
  7574. //---------------------------------------------------------------------------
  7575. //-- no_hash --
  7576. class HashCodeCreator
  7577. {
  7578. public:
  7579. HashCodeCreator(HqlCppTranslator & _translator, const CHqlBoundTarget & _target, node_operator _hashKind, bool _optimizeInternal)
  7580. : translator(_translator), target(_target), hashKind(_hashKind), optimizeInternal(_optimizeInternal)
  7581. {
  7582. prevFunc = NULL;
  7583. }
  7584. //Combine calls to the hash function on adjacent memory to minimise the number of calls
  7585. //and the generated code size.
  7586. void buildHash(BuildCtx & ctx, _ATOM func, IHqlExpression * length, IHqlExpression * ptr)
  7587. {
  7588. if ((func == hash32DataAtom) || (func == hash64DataAtom))
  7589. {
  7590. ptr = stripTranslatedCasts(ptr);
  7591. if (prevFunc)
  7592. {
  7593. if ((prevFunc == func) && rightFollowsLeft(prevPtr, prevLength, ptr))
  7594. {
  7595. prevLength.setown(peepholeAddExpr(prevLength, length));
  7596. return;
  7597. }
  7598. flush(ctx);
  7599. }
  7600. prevFunc = func;
  7601. prevLength.set(length);
  7602. prevPtr.set(ptr);
  7603. return;
  7604. }
  7605. flush(ctx);
  7606. buildCall(ctx, func, length, ptr);
  7607. }
  7608. void beginCondition(BuildCtx & ctx)
  7609. {
  7610. ensureInitialAssigned(ctx);
  7611. flush(ctx);
  7612. }
  7613. void endCondition(BuildCtx & ctx)
  7614. {
  7615. flush(ctx);
  7616. }
  7617. void finish(BuildCtx & ctx)
  7618. {
  7619. flush(ctx);
  7620. ensureInitialAssigned(ctx);
  7621. }
  7622. void setInitialValue(IHqlExpression * expr)
  7623. {
  7624. initialValue.set(expr);
  7625. }
  7626. inline node_operator kind() const { return hashKind; }
  7627. inline bool optimize() const { return optimizeInternal; }
  7628. protected:
  7629. void buildCall(BuildCtx & ctx, _ATOM func, IHqlExpression * length, IHqlExpression * ptr)
  7630. {
  7631. if (func == hash32DataAtom)
  7632. {
  7633. unsigned fixedSize = (unsigned)getIntValue(length, 0);
  7634. switch (fixedSize)
  7635. {
  7636. case 1: func = hash32Data1Atom; break;
  7637. case 2: func = hash32Data2Atom; break;
  7638. case 3: func = hash32Data3Atom; break;
  7639. case 4: func = hash32Data4Atom; break;
  7640. case 5: func = hash32Data5Atom; break;
  7641. case 6: func = hash32Data6Atom; break;
  7642. case 7: func = hash32Data7Atom; break;
  7643. case 8: func = hash32Data8Atom; break;
  7644. }
  7645. if (func != hash32DataAtom)
  7646. length = NULL;
  7647. }
  7648. HqlExprArray args;
  7649. if (length)
  7650. args.append(*LINK(length));
  7651. args.append(*LINK(ptr));
  7652. if (initialValue)
  7653. args.append(*initialValue.getClear());
  7654. else
  7655. args.append(*LINK(target.expr));
  7656. CHqlBoundExpr boundHash;
  7657. boundHash.expr.setown(translator.bindTranslatedFunctionCall(func, args));
  7658. translator.assign(ctx, target, boundHash);
  7659. }
  7660. void ensureInitialAssigned(BuildCtx & ctx)
  7661. {
  7662. if (initialValue)
  7663. {
  7664. translator.assignBound(ctx, target, initialValue);
  7665. initialValue.clear();
  7666. }
  7667. }
  7668. void flush(BuildCtx & ctx)
  7669. {
  7670. if (prevFunc)
  7671. {
  7672. buildCall(ctx, prevFunc, prevLength, prevPtr);
  7673. prevFunc = NULL;
  7674. }
  7675. }
  7676. protected:
  7677. HqlCppTranslator & translator;
  7678. const CHqlBoundTarget & target;
  7679. LinkedHqlExpr initialValue;
  7680. node_operator hashKind;
  7681. bool optimizeInternal;
  7682. _ATOM prevFunc;
  7683. OwnedHqlExpr prevLength;
  7684. OwnedHqlExpr prevPtr;
  7685. };
  7686. void HqlCppTranslator::doBuildAssignHashCrc(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  7687. {
  7688. IHqlExpression * child = expr->queryChild(0);
  7689. ITypeInfo * childType = child->queryType();
  7690. LinkedHqlExpr initialValue = queryZero();
  7691. node_operator op = expr->getOperator();
  7692. if (op == no_hash32)
  7693. initialValue.setown(createConstant(createIntValue(0x811C9DC5, 4, false)));
  7694. else if (op == no_hash64)
  7695. initialValue.setown(createConstant(createIntValue(I64C(0xcbf29ce484222325), 8, false)));
  7696. HashCodeCreator creator(*this, target, op, expr->hasProperty(internalAtom));
  7697. creator.setInitialValue(initialValue);
  7698. if (child->getOperator() != no_sortlist)
  7699. doBuildAssignHashElement(ctx, creator, child);
  7700. else
  7701. {
  7702. unsigned max = child->numChildren();
  7703. unsigned idx;
  7704. for (idx = 0; idx < max; idx++)
  7705. doBuildAssignHashElement(ctx, creator, child->queryChild(idx));
  7706. }
  7707. creator.finish(ctx);
  7708. }
  7709. void HqlCppTranslator::doBuildAssignHashElement(BuildCtx & ctx, HashCodeCreator & creator, IHqlExpression * elem, IHqlExpression * record)
  7710. {
  7711. bool useNewSelector = elem->isDatarow() && ((elem->getOperator() != no_select) || isNewSelector(elem));
  7712. ForEachChild(i, record)
  7713. {
  7714. IHqlExpression * cur = record->queryChild(i);
  7715. switch (cur->getOperator())
  7716. {
  7717. case no_field:
  7718. {
  7719. OwnedHqlExpr selected = useNewSelector ? createNewSelectExpr(LINK(elem), LINK(cur)) : createSelectExpr(LINK(elem), LINK(cur));
  7720. doBuildAssignHashElement(ctx, creator, selected);
  7721. break;
  7722. }
  7723. case no_record:
  7724. doBuildAssignHashElement(ctx, creator, elem, cur);
  7725. break;
  7726. case no_ifblock:
  7727. doBuildAssignHashElement(ctx, creator, elem, cur->queryChild(1));
  7728. break;
  7729. }
  7730. }
  7731. }
  7732. void HqlCppTranslator::doBuildAssignHashElement(BuildCtx & ctx, HashCodeCreator & creator, IHqlExpression * elem)
  7733. {
  7734. if (creator.optimize())
  7735. {
  7736. switch (elem->getOperator())
  7737. {
  7738. case no_if:
  7739. {
  7740. BuildCtx subctx(ctx);
  7741. creator.beginCondition(subctx);
  7742. IHqlStmt * cond = buildFilterViaExpr(subctx, elem->queryChild(0));
  7743. doBuildAssignHashElement(subctx, creator, elem->queryChild(1));
  7744. creator.endCondition(subctx);
  7745. IHqlExpression * elseValue = elem->queryChild(2);
  7746. if (elseValue && elseValue->getOperator() != no_constant)
  7747. {
  7748. subctx.selectElse(cond);
  7749. creator.beginCondition(subctx);
  7750. doBuildAssignHashElement(subctx, creator, elseValue);
  7751. creator.endCondition(subctx);
  7752. }
  7753. return;
  7754. }
  7755. case no_constant:
  7756. return;
  7757. }
  7758. }
  7759. Linked<ITypeInfo> type = elem->queryType()->queryPromotedType(); // skip alien data types, to logical type.
  7760. if (type->getTypeCode() == type_row)
  7761. {
  7762. doBuildAssignHashElement(ctx, creator, elem, elem->queryRecord());
  7763. return;
  7764. }
  7765. _ATOM func=NULL;
  7766. switch (creator.kind())
  7767. {
  7768. case no_hash: func = hashDataAtom; break;
  7769. case no_hash32: func = hash32DataAtom; break;
  7770. case no_hash64: func = hash64DataAtom; break;
  7771. case no_crc: func = crcDataAtom; break;
  7772. }
  7773. CHqlBoundExpr bound;
  7774. OwnedHqlExpr length;
  7775. OwnedHqlExpr ptr;
  7776. bool alreadyTrimmedRight = (elem->getOperator() == no_trim) && (elem->hasProperty(rightAtom) || !elem->hasProperty(leftAtom));
  7777. //If this hash is generated internally (e.g., for a dedup) and fixed length, then can simplify the hash calculation
  7778. bool canOptimizeHash = (creator.optimize() && isFixedSize(type));
  7779. bool optimizeTrim = alreadyTrimmedRight || canOptimizeHash;
  7780. switch (type->getTypeCode())
  7781. {
  7782. case type_string:
  7783. {
  7784. if (!optimizeTrim)
  7785. {
  7786. OwnedHqlExpr trimmed = createValue(no_trim, getStretchedType(UNKNOWN_LENGTH, type), LINK(elem));
  7787. buildCachedExpr(ctx, trimmed, bound);
  7788. }
  7789. else
  7790. buildCachedExpr(ctx, elem, bound);
  7791. length.setown(getBoundLength(bound));
  7792. ptr.setown(getElementPointer(bound.expr));
  7793. }
  7794. break;
  7795. case type_unicode:
  7796. {
  7797. if (!optimizeTrim)
  7798. {
  7799. OwnedHqlExpr trimmed = createValue(no_trim, getStretchedType(UNKNOWN_LENGTH, type), LINK(elem));
  7800. buildCachedExpr(ctx, trimmed, bound);
  7801. }
  7802. else
  7803. buildCachedExpr(ctx, elem, bound);
  7804. length.setown(getBoundLength(bound));
  7805. ptr.setown(getElementPointer(bound.expr));
  7806. switch (creator.kind())
  7807. {
  7808. case no_hash: func = hashUnicodeAtom; break;
  7809. case no_hash32: func = hash32UnicodeAtom; break;
  7810. case no_hash64: func = hash64UnicodeAtom; break;
  7811. case no_crc: func = crcUnicodeAtom; break;
  7812. }
  7813. }
  7814. break;
  7815. case type_utf8:
  7816. {
  7817. if (!optimizeTrim)
  7818. {
  7819. OwnedHqlExpr trimmed = createValue(no_trim, getStretchedType(UNKNOWN_LENGTH, type), LINK(elem));
  7820. buildCachedExpr(ctx, trimmed, bound);
  7821. }
  7822. else
  7823. buildCachedExpr(ctx, elem, bound);
  7824. length.setown(getBoundLength(bound));
  7825. ptr.setown(getElementPointer(bound.expr));
  7826. switch (creator.kind())
  7827. {
  7828. case no_hash: func = hashUtf8Atom; break;
  7829. case no_hash32: func = hash32Utf8Atom; break;
  7830. case no_hash64: func = hash64Utf8Atom; break;
  7831. case no_crc: func = crcUtf8Atom; break;
  7832. }
  7833. }
  7834. break;
  7835. case type_data:
  7836. {
  7837. buildCachedExpr(ctx, elem, bound);
  7838. length.setown(getBoundLength(bound));
  7839. ptr.setown(getElementPointer(bound.expr));
  7840. break;
  7841. }
  7842. case type_qstring:
  7843. {
  7844. LinkedHqlExpr exprToHash = elem;
  7845. if (!canOptimizeHash)
  7846. {
  7847. //Always convert to a string so the hash is compatible with a string.
  7848. OwnedHqlExpr cast = ensureExprType(elem, unknownStringType);
  7849. if (alreadyTrimmedRight)
  7850. {
  7851. exprToHash.set(cast);
  7852. }
  7853. else
  7854. {
  7855. OwnedHqlExpr trimmed = createValue(no_trim, LINK(unknownStringType), LINK(cast));
  7856. exprToHash.setown(foldHqlExpression(trimmed));
  7857. }
  7858. }
  7859. buildCachedExpr(ctx, exprToHash, bound);
  7860. length.setown(getBoundSize(bound));
  7861. ptr.setown(getElementPointer(bound.expr));
  7862. break;
  7863. }
  7864. case type_varstring:
  7865. buildCachedExpr(ctx, elem, bound);
  7866. ptr.setown(getElementPointer(bound.expr));
  7867. switch (creator.kind())
  7868. {
  7869. case no_hash: func = hashVStrAtom; break;
  7870. case no_hash32: func = hash32VStrAtom; break;
  7871. case no_hash64: func = hash64VStrAtom; break;
  7872. case no_crc: func = crcVStrAtom; break;
  7873. }
  7874. break;
  7875. case type_varunicode:
  7876. buildCachedExpr(ctx, elem, bound);
  7877. ptr.setown(getElementPointer(bound.expr));
  7878. switch (creator.kind())
  7879. {
  7880. case no_hash: func = hashVUnicodeAtom; break;
  7881. case no_hash32: func = hash32VUnicodeAtom; break;
  7882. case no_hash64: func = hash64VUnicodeAtom; break;
  7883. case no_crc: func = crcVUnicodeAtom; break;
  7884. }
  7885. break;
  7886. case type_boolean:
  7887. case type_int:
  7888. case type_swapint:
  7889. case type_real:
  7890. if (creator.optimize() && hasAddress(ctx, elem))
  7891. {
  7892. buildAddress(ctx, elem, bound);
  7893. length.setown(getSizetConstant(type->getSize()));
  7894. ptr.setown(LINK(bound.expr));
  7895. }
  7896. else
  7897. {
  7898. if (!creator.optimize())
  7899. type.setown(makeIntType(8, true));
  7900. OwnedHqlExpr castElem = ensureExprType(elem, type);
  7901. buildTempExpr(ctx, castElem, bound);
  7902. length.setown(getSizetConstant(type->getSize()));
  7903. ptr.setown(getPointer(bound.expr));
  7904. }
  7905. break;
  7906. case type_row:
  7907. throwUnexpected();
  7908. break;
  7909. case type_groupedtable:
  7910. case type_table:
  7911. //MORE: Should be handle this differently, with an iterator for the link counted rows case?
  7912. //Not sure if that is a good idea - we need to be certain we get the same values with
  7913. //LCR rows enabled and disabled. But this won't be very efficient with lcr rows.
  7914. //fallthrough
  7915. if (creator.optimize() && hasOutOfLineRows(elem->queryType()))
  7916. {
  7917. BuildCtx iterctx(ctx);
  7918. BoundRow * row = buildDatasetIterate(iterctx, elem, false);
  7919. doBuildAssignHashElement(iterctx, creator, elem->queryNormalizedSelector(), elem->queryRecord());
  7920. return;
  7921. }
  7922. else
  7923. {
  7924. OwnedHqlExpr serialized = ::ensureSerialized(elem);
  7925. buildDataset(ctx, serialized, bound, FormatBlockedDataset);
  7926. length.setown(getBoundSize(bound));
  7927. ptr.setown(getPointer(bound.expr));
  7928. }
  7929. break;
  7930. default:
  7931. buildTempExpr(ctx, elem, bound, FormatBlockedDataset);
  7932. length.setown(getBoundSize(bound));
  7933. ptr.setown(getPointer(bound.expr));
  7934. break;
  7935. }
  7936. creator.buildHash(ctx, func, length, ptr);
  7937. }
  7938. //---------------------------------------------------------------------------
  7939. //-- no_hash --
  7940. void HqlCppTranslator::doBuildAssignHashMd5(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  7941. {
  7942. IHqlExpression * child = expr->queryChild(0);
  7943. ITypeInfo * childType = child->queryType();
  7944. Owned<ITypeInfo> stateType = makeDataType(sizeof(md5_state_s));
  7945. //initialize the state object
  7946. CHqlBoundTarget stateTemp;
  7947. CHqlBoundExpr state;
  7948. createTempFor(ctx, stateType, stateTemp, typemod_none, FormatNatural);
  7949. state.setFromTarget(stateTemp);
  7950. OwnedHqlExpr stateExpr = state.getTranslatedExpr();
  7951. HqlExprArray args;
  7952. args.append(*LINK(stateExpr));
  7953. OwnedHqlExpr callInit = bindFunctionCall(hashMd5InitAtom, args);
  7954. buildStmt(ctx, callInit);
  7955. //Now hash each of the elements in turn.
  7956. if (child->getOperator() != no_sortlist)
  7957. doBuildHashMd5Element(ctx, child, state);
  7958. else
  7959. {
  7960. unsigned max = child->numChildren();
  7961. for (unsigned idx = 0; idx < max; idx++)
  7962. doBuildHashMd5Element(ctx, child->queryChild(idx), state);
  7963. }
  7964. //finalise the md5, and get the result.
  7965. args.append(*LINK(stateExpr));
  7966. OwnedHqlExpr callFinish = bindFunctionCall(hashMd5FinishAtom, args);
  7967. buildExprAssign(ctx, target, callFinish);
  7968. }
  7969. void HqlCppTranslator::doBuildHashMd5Element(BuildCtx & ctx, IHqlExpression * elem, CHqlBoundExpr & state)
  7970. {
  7971. CHqlBoundExpr bound;
  7972. Linked<ITypeInfo> type = elem->queryType()->queryPromotedType(); // skip alien data types, to logical type.
  7973. HqlExprArray args;
  7974. _ATOM func=NULL;
  7975. switch (type->getTypeCode())
  7976. {
  7977. case type_string:
  7978. case type_unicode:
  7979. case type_data:
  7980. case type_qstring:
  7981. case type_varstring:
  7982. case type_varunicode:
  7983. case type_utf8:
  7984. buildExpr(ctx, elem, bound);
  7985. args.append(*getBoundSize(bound));
  7986. args.append(*getElementPointer(bound.expr));
  7987. break;
  7988. case type_int:
  7989. case type_swapint:
  7990. case type_packedint:
  7991. {
  7992. type.setown(makeIntType(8, true));
  7993. OwnedHqlExpr castElem = ensureExprType(elem, type);
  7994. buildTempExpr(ctx, castElem, bound);
  7995. args.append(*getSizetConstant(type->getSize()));
  7996. args.append(*getPointer(bound.expr));
  7997. break;
  7998. }
  7999. default:
  8000. buildTempExpr(ctx, elem, bound);
  8001. args.append(*getSizetConstant(type->getSize()));
  8002. args.append(*getPointer(bound.expr));
  8003. break;
  8004. }
  8005. args.append(*getBoundSize(state));
  8006. args.append(*LINK(state.expr));
  8007. OwnedHqlExpr call = bindTranslatedFunctionCall(hashMd5DataAtom, args);
  8008. ctx.addExpr(call);
  8009. }
  8010. //---------------------------------------------------------------------------
  8011. void HqlCppTranslator::doBuildExprTransfer(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8012. {
  8013. CHqlBoundExpr bound;
  8014. //Ensure the bound result has an address
  8015. IHqlExpression * src = expr->queryChild(0);
  8016. bool gotAddress = false;
  8017. if (src->isDataset())
  8018. {
  8019. buildDataset(ctx, src, bound, FormatBlockedDataset);
  8020. bound.expr.setown(getPointer(bound.expr));
  8021. }
  8022. else if (src->isDatarow())
  8023. {
  8024. Owned<IReferenceSelector> ref = buildNewRow(ctx, src);
  8025. ref->get(ctx, bound);
  8026. bound.expr.setown(getPointer(bound.expr));
  8027. }
  8028. else if (isTypePassedByAddress(src->queryType()))
  8029. buildCachedExpr(ctx, src, bound);
  8030. else if (hasAddress(ctx, src))
  8031. {
  8032. buildAddress(ctx, src, bound);
  8033. gotAddress = true;
  8034. }
  8035. else
  8036. buildTempExpr(ctx, src, bound);
  8037. OwnedITypeInfo from = bound.expr->getType();
  8038. ITypeInfo * to = expr->queryType();
  8039. //Must calculate the size of the bound value before we start messing about with stripping casts etc.
  8040. OwnedHqlExpr size;
  8041. if (to->getSize() == UNKNOWN_LENGTH)
  8042. {
  8043. if (from->getSize() == UNKNOWN_LENGTH)
  8044. size.setown(getBoundSize(bound));
  8045. else
  8046. size.setown(getSizetConstant(from->getSize()));
  8047. }
  8048. if (!isTypePassedByAddress(from) && !gotAddress)
  8049. bound.expr.setown(getAddress(bound.expr));
  8050. //strip unnecessary casts...
  8051. while (bound.expr->getOperator() == no_implicitcast)
  8052. bound.expr.set(bound.expr->queryChild(0));
  8053. if (isTypePassedByAddress(to))
  8054. {
  8055. to->Link();
  8056. if (!to->isReference())
  8057. to = makeReferenceModifier(to);
  8058. tgt.expr.setown(createValue(no_implicitcast, to, LINK(bound.expr)));
  8059. if (to->getSize() == UNKNOWN_LENGTH)
  8060. {
  8061. switch (to->getTypeCode())
  8062. {
  8063. case type_unicode:
  8064. if (size->isConstant())
  8065. tgt.length.setown(getSizetConstant((size32_t)getIntValue(size)/sizeof(UChar)));
  8066. else
  8067. tgt.length.setown(createValue(no_div, LINK(sizetType), LINK(size), getSizetConstant(2)));
  8068. break;
  8069. case type_qstring:
  8070. if (size->isConstant())
  8071. tgt.length.setown(getSizetConstant(rtlQStrLength((size32_t)getIntValue(size))));
  8072. else
  8073. tgt.length.setown(createValue(no_div, LINK(sizetType), multiplyValue(size, 4), getSizetConstant(3)));
  8074. break;
  8075. case type_varstring:
  8076. case type_varunicode:
  8077. break;
  8078. default:
  8079. tgt.length.set(size);
  8080. break;
  8081. }
  8082. }
  8083. }
  8084. else
  8085. {
  8086. tgt.length.clear();
  8087. tgt.expr.set(bound.expr);
  8088. if (hasWrapperModifier(tgt.expr->queryType()))
  8089. tgt.expr.setown(createValue(no_implicitcast, makeReferenceModifier(LINK(queryUnqualifiedType(from))), LINK(tgt.expr)));
  8090. tgt.expr.setown(createValue(no_implicitcast, makePointerType(LINK(to)), tgt.expr.getClear()));
  8091. tgt.expr.setown(createValue(no_deref, LINK(to), tgt.expr.getClear()));
  8092. }
  8093. }
  8094. //---------------------------------------------------------------------------
  8095. //-- no_ordered
  8096. void HqlCppTranslator::doBuildExprOrdered(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8097. {
  8098. if (ctx.getMatchExpr(expr, tgt))
  8099. return;
  8100. bool ascending = true;
  8101. OwnedHqlExpr list = simplifyFixedLengthList(expr->queryChild(0));
  8102. IHqlExpression * attr = expr->queryChild(1);
  8103. if (attr && attr->isAttribute() && (attr->queryName() == descAtom))
  8104. ascending = false;
  8105. if (list->numChildren() == 0)
  8106. throwError(HQLERR_RankOnNull);
  8107. //create the list that is going to be sorted
  8108. CHqlBoundExpr boundList;
  8109. OwnedHqlExpr optimalList = getOptimialListFormat(list);
  8110. buildExpr(ctx, optimalList, boundList);
  8111. //create a compare function....
  8112. ITypeInfo * elementType = boundList.expr->queryType()->queryChildType();
  8113. unsigned elementSize = elementType->getSize();
  8114. if (elementSize == UNKNOWN_LENGTH)
  8115. throwError(HQLERR_OrderOnVarlengthStrings);
  8116. StringBuffer tempName;
  8117. getUniqueId(tempName.append('v'));
  8118. IHqlExpression * tempCompare = createVariable(tempName.str(), makeVoidType());
  8119. StringBuffer s;
  8120. s.clear().append("extern int ").append(tempName).append("(const void * left, const void * right);");
  8121. if (options.spanMultipleCpp)
  8122. {
  8123. BuildCtx protoctx(*code, mainprototypesAtom);
  8124. protoctx.addQuoted(s);
  8125. }
  8126. else
  8127. {
  8128. BuildCtx protoctx(*code, prototypeAtom);
  8129. protoctx.addQuoted(s);
  8130. }
  8131. BuildCtx declareCtx(*code, declareAtom);
  8132. s.clear().append("int ").append(tempName).append("(const void * left, const void * right)");
  8133. declareCtx.addQuotedCompound(s);
  8134. Owned<ITypeInfo> argType;
  8135. if (isTypePassedByAddress(elementType) && !hasReferenceModifier(elementType))
  8136. argType.setown(makeReferenceModifier(LINK(elementType)));
  8137. else
  8138. argType.setown(makePointerType(LINK(elementType)));
  8139. OwnedHqlExpr leftAddr = createVariable("left", LINK(argType));
  8140. OwnedHqlExpr rightAddr = createVariable("right", LINK(argType));
  8141. IHqlExpression * left = convertAddressToValue(leftAddr, elementType);
  8142. IHqlExpression * right = convertAddressToValue(rightAddr, elementType);
  8143. if (elementType->isReference())
  8144. elementSize = sizeof(char * *);
  8145. left = createTranslatedOwned(left);
  8146. right = createTranslatedOwned(right);
  8147. OwnedHqlExpr compare;
  8148. if (ascending)
  8149. compare.setown(createValue(no_order, LINK(signedType), left, right));
  8150. else
  8151. compare.setown(createValue(no_order, LINK(signedType), right, left));
  8152. CHqlBoundExpr boundCompare;
  8153. buildExpr(declareCtx, compare, boundCompare);
  8154. declareCtx.setNextDestructor();
  8155. declareCtx.addReturn(boundCompare.expr);
  8156. //Allocate an array to store the orders
  8157. unsigned max = list->numChildren();
  8158. Owned<ITypeInfo> t = makeArrayType(LINK(unsignedType), max);
  8159. IHqlExpression * table = ctx.getTempDeclare(t, NULL);
  8160. ctx.associateExpr(expr, table);
  8161. //Generate the call to the function that calculates the orders
  8162. IHqlExpression * castCompare = createValue(no_implicitcast, makePointerType(makeVoidType()), tempCompare);
  8163. HqlExprArray args;
  8164. args.append(*getPointer(table));
  8165. args.append(*getPointer(boundList.expr));
  8166. args.append(*createConstant(unsignedType->castFrom(false, max)));
  8167. args.append(*getSizetConstant(elementSize));
  8168. args.append(*castCompare);
  8169. callProcedure(ctx, createOrderAtom, args);
  8170. tgt.expr.setown(table);
  8171. }
  8172. //---------------------------------------------------------------------------
  8173. //-- no_rank
  8174. void checkRankRange(IHqlExpression * index, IHqlExpression * list)
  8175. {
  8176. IValue * indexValue = index->queryValue();
  8177. if (indexValue)
  8178. {
  8179. unsigned max = list->numChildren();
  8180. unsigned idx = (unsigned)indexValue->getIntValue();
  8181. //MORE: Should be a warning.....
  8182. if ((idx < 1) || (idx > max))
  8183. throwError(HQLERR_RankOutOfRange);
  8184. }
  8185. //MORE: Could dynamically allocate the array indexes...
  8186. if (list->getOperator() == no_getresult)
  8187. {
  8188. StringBuffer s;
  8189. IHqlExpression * sequence = queryPropertyChild(list, sequenceAtom, 0);
  8190. IHqlExpression * name = queryPropertyChild(list, namedAtom, 0);
  8191. getStoredDescription(s, sequence, name, true);
  8192. throwError1(HQLERR_RankOnStored, s.str());
  8193. }
  8194. }
  8195. void HqlCppTranslator::createOrderList(BuildCtx & ctx, IHqlExpression * expr, IHqlExpression * ascdesc, CHqlBoundExpr & tgt)
  8196. {
  8197. ITypeInfo * orderedType = makeArrayType(LINK(unsignedType), expr->numChildren());
  8198. OwnedHqlExpr ordered = createValue(no_ordered, orderedType, LINK(expr), LINK(ascdesc));
  8199. buildExpr(ctx, ordered, tgt);
  8200. }
  8201. void HqlCppTranslator::doBuildExprRank(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8202. {
  8203. IHqlExpression * index = expr->queryChild(0);
  8204. IHqlExpression * list = expr->queryChild(1);
  8205. checkRankRange(index, list);
  8206. CHqlBoundExpr bound, boundIndex;
  8207. createOrderList(ctx, list, expr->queryChild(2), bound);
  8208. buildExpr(ctx, index, boundIndex);
  8209. HqlExprArray args;
  8210. args.append(*boundIndex.expr.getClear());
  8211. args.append(*createConstant(unsignedType->castFrom(false, list->numChildren())));
  8212. args.append(*getPointer(bound.expr));
  8213. tgt.expr.setown(bindTranslatedFunctionCall(rankFromOrderAtom, args));
  8214. }
  8215. //---------------------------------------------------------------------------
  8216. //-- no_ranked
  8217. void HqlCppTranslator::doBuildExprRanked(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8218. {
  8219. IHqlExpression * index = expr->queryChild(0);
  8220. IHqlExpression * list = expr->queryChild(1);
  8221. checkRankRange(index, list);
  8222. CHqlBoundExpr bound, boundIndex;
  8223. createOrderList(ctx, list, expr->queryChild(2), bound);
  8224. buildExpr(ctx, index, boundIndex);
  8225. HqlExprArray args;
  8226. args.append(*boundIndex.expr.getClear());
  8227. args.append(*createConstant(unsignedType->castFrom(false, list->numChildren())));
  8228. args.append(*getPointer(bound.expr));
  8229. tgt.expr.setown(bindTranslatedFunctionCall(rankedFromOrderAtom, args));
  8230. }
  8231. //---------------------------------------------------------------------------
  8232. //-- no_fail
  8233. void HqlCppTranslator::doBuildStmtFail(BuildCtx & ctx, IHqlExpression * expr)
  8234. {
  8235. HqlExprArray args;
  8236. args.append(*getFailCode(expr));
  8237. args.append(*getFailMessage(expr, false));
  8238. _ATOM func = expr->hasProperty(defaultAtom) ? sysFailAtom : _failIdAtom;
  8239. OwnedHqlExpr call = bindFunctionCall(func, args);
  8240. buildStmt(ctx, call);
  8241. }
  8242. void HqlCppTranslator::doBuildExprFailCode(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8243. {
  8244. OwnedHqlExpr activeFailMarker = createAttribute(activeFailureAtom);
  8245. HqlExprAssociation * matchedMarker = ctx.queryMatchExpr(activeFailMarker);
  8246. if (!matchedMarker && !ctx.queryMatchExpr(globalContextMarkerExpr))
  8247. {
  8248. if (!buildExprInCorrectContext(ctx, expr, tgt, false))
  8249. throwError1(HQLERR_FailXUsedOutsideFailContext, getOpString(expr->getOperator()));
  8250. return;
  8251. }
  8252. HqlExprArray args;
  8253. if (matchedMarker)
  8254. {
  8255. args.append(*LINK(matchedMarker->queryExpr()));
  8256. tgt.expr.setown(bindTranslatedFunctionCall(queryLocalFailCodeAtom, args));
  8257. }
  8258. else
  8259. {
  8260. tgt.expr.setown(bindTranslatedFunctionCall(queryFailCodeAtom, args));
  8261. }
  8262. }
  8263. void HqlCppTranslator::doBuildAssignFailMessage(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8264. {
  8265. OwnedHqlExpr activeFailMarker = createAttribute(activeFailureAtom);
  8266. HqlExprAssociation * matchedMarker = ctx.queryMatchExpr(activeFailMarker);
  8267. if (!matchedMarker && !ctx.queryMatchExpr(globalContextMarkerExpr))
  8268. {
  8269. CHqlBoundExpr match;
  8270. if (!buildExprInCorrectContext(ctx, expr, match, false))
  8271. throwError1(HQLERR_FailXUsedOutsideFailContext, getOpString(expr->getOperator()));
  8272. assign(ctx, target, match);
  8273. return;
  8274. }
  8275. _ATOM func = getFailMessageAtom;
  8276. HqlExprArray args;
  8277. if (matchedMarker)
  8278. {
  8279. func = getLocalFailMessageAtom;
  8280. args.append(*createTranslated(matchedMarker->queryExpr()));
  8281. }
  8282. LinkedHqlExpr tag = expr->queryChild(0);
  8283. if (!tag)
  8284. tag.setown(createQuoted("0", makeConstantModifier(makeReferenceModifier(makeVarStringType(UNKNOWN_LENGTH, 0, 0)))));
  8285. args.append(*LINK(tag));
  8286. OwnedHqlExpr call = bindFunctionCall(func, args);
  8287. buildExprAssign(ctx, target, call);
  8288. }
  8289. void HqlCppTranslator::doBuildAssignEventName(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8290. {
  8291. HqlExprArray args;
  8292. OwnedHqlExpr call = bindFunctionCall(getEventNameAtom, args);
  8293. buildExprAssign(ctx, target, call);
  8294. }
  8295. void HqlCppTranslator::doBuildAssignEventExtra(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8296. {
  8297. LinkedHqlExpr tag = expr->queryChild(0);
  8298. if (!tag)
  8299. tag.setown(createQuoted("0", makeConstantModifier(makeReferenceModifier(makeVarStringType(UNKNOWN_LENGTH, 0, 0)))));
  8300. HqlExprArray args;
  8301. args.append(*LINK(tag));
  8302. OwnedHqlExpr call = bindFunctionCall(getEventExtraAtom, args);
  8303. buildExprAssign(ctx, target, call);
  8304. }
  8305. //---------------------------------------------------------------------------
  8306. //-- system call e.g. EXP(), LOG()...
  8307. void HqlCppTranslator::doBuildExprSysFunc(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt, IAtom * funcName)
  8308. {
  8309. HqlExprArray args;
  8310. ForEachChild(i, expr)
  8311. {
  8312. IHqlExpression * cur = expr->queryChild(i);
  8313. if (!cur->isAttribute())
  8314. args.append(*LINK(cur));
  8315. }
  8316. OwnedHqlExpr call = bindFunctionCall(funcName, args);
  8317. buildExpr(ctx, call, tgt);
  8318. }
  8319. void HqlCppTranslator::doBuildExprOffsetOf(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8320. {
  8321. if (ctx.getMatchExpr(expr, tgt))
  8322. return;
  8323. IHqlExpression * arg = expr->queryChild(0);
  8324. Owned<IReferenceSelector> selector = buildActiveReference(ctx, arg);
  8325. selector->getOffset(ctx, tgt);
  8326. //cache non-constant values in a temporary variable...
  8327. if (!isSimpleLength(tgt.expr))
  8328. {
  8329. IHqlExpression * temp = ctx.getTempDeclare(expr->queryType(), tgt.expr);
  8330. tgt.expr.setown(temp);
  8331. ctx.associateExpr(expr, tgt);
  8332. }
  8333. }
  8334. //---------------------------------------------------------------------------
  8335. //-- no_subselect --
  8336. void HqlCppTranslator::doBuildAssignSubString(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8337. {
  8338. if (expr->queryChild(1)->getOperator() == no_rangecommon)
  8339. throwError(HQLERR_StarRangeOnlyInJoinCondition);
  8340. ITypeInfo * resultType = expr->queryType();
  8341. ITypeInfo * targetType = target.queryType();
  8342. type_t rtc = resultType->getTypeCode();
  8343. type_t ttc = targetType->getTypeCode();
  8344. SubStringInfo info(expr);
  8345. CHqlBoundExpr newBound;
  8346. bool doneAssign = false;
  8347. if (info.special)
  8348. doBuildExprSpecialSubString(ctx, info, newBound);
  8349. else if (info.infiniteString)
  8350. doBuildExprInfiniteSubString(ctx, info, newBound);
  8351. if (!newBound.expr)
  8352. {
  8353. _ATOM func = NULL;
  8354. type_t stc = info.src->queryType()->getTypeCode();
  8355. if (target.isFixedSize())
  8356. {
  8357. switch (ttc)
  8358. {
  8359. case type_qstring:
  8360. if (stc == type_qstring)
  8361. func = subQStrFTAtom;
  8362. break;
  8363. case type_data:
  8364. switch (stc)
  8365. {
  8366. case type_data:
  8367. case type_string:
  8368. case type_varstring:
  8369. func = subDataFTAtom;
  8370. break;
  8371. }
  8372. break;
  8373. case type_string:
  8374. switch (stc)
  8375. {
  8376. case type_data:
  8377. func = subDataFTAtom;
  8378. break;
  8379. case type_string:
  8380. case type_varstring:
  8381. if (resultType->queryCharset() == info.src->queryType()->queryCharset())
  8382. func = subStrFTAtom;
  8383. break;
  8384. }
  8385. break;
  8386. }
  8387. if (!func && (queryUnqualifiedType(resultType) != queryUnqualifiedType(targetType)))
  8388. {
  8389. CHqlBoundExpr bound;
  8390. buildTempExpr(ctx, expr, bound);
  8391. assign(ctx, target, bound);
  8392. return;
  8393. }
  8394. }
  8395. CHqlBoundExpr boundSrc;
  8396. buildCachedExpr(ctx, info.src, boundSrc);
  8397. info.bindToFrom(*this, ctx);
  8398. ITypeInfo * sourceType = boundSrc.queryType();
  8399. if (!info.boundFrom.expr)
  8400. info.boundFrom.expr.setown(getSizetConstant(1));
  8401. //Some hacks to force the parameters/return values to the same type. It could be solved more cleanly,
  8402. //but with more functions by calling different functions instead.
  8403. CHqlBoundTarget tempTarget;
  8404. tempTarget.set(target);
  8405. switch (rtc)
  8406. {
  8407. case type_string:
  8408. if (resultType->queryCollation()->queryName() != asciiAtom)
  8409. {
  8410. unsigned sourceLen = boundSrc.queryType()->getStringLen();
  8411. boundSrc.expr.setown(createValue(no_typetransfer, makeStringType(sourceLen, NULL, NULL), LINK(boundSrc.expr)));
  8412. OwnedITypeInfo newTargetType = makeStringType(targetType->getStringLen(), NULL, NULL);
  8413. tempTarget.expr.setown(createValue(no_typetransfer, cloneModifiers(targetType, newTargetType), LINK(tempTarget.expr)));
  8414. }
  8415. break;
  8416. }
  8417. HqlExprArray args;
  8418. args.append(*boundSrc.getTranslatedExpr());
  8419. args.append(*info.boundFrom.getTranslatedExpr());
  8420. if (func)
  8421. {
  8422. args.add(*createTranslated(tempTarget.expr), 0);
  8423. if (info.boundTo.expr)
  8424. args.append(*info.boundTo.getTranslatedExpr());
  8425. else
  8426. args.append(*createConstant(unsignedType->castFrom(false, 0x7fffffff)));
  8427. OwnedHqlExpr call = bindFunctionCall(func, args);
  8428. buildStmt(ctx, call);
  8429. }
  8430. else
  8431. {
  8432. if (info.boundTo.expr)
  8433. {
  8434. args.append(*info.boundTo.getTranslatedExpr());
  8435. switch (rtc)
  8436. {
  8437. case type_qstring:
  8438. func = subQStrFTXAtom;
  8439. break;
  8440. case type_data:
  8441. func = subDataFTXAtom;
  8442. break;
  8443. case type_unicode:
  8444. case type_varunicode:
  8445. func = unicodeSubStrFTXAtom;
  8446. break;
  8447. case type_utf8:
  8448. func = utf8SubStrFTXAtom;
  8449. break;
  8450. default:
  8451. func = subStrFTXAtom;
  8452. break;
  8453. }
  8454. }
  8455. else
  8456. {
  8457. switch (rtc)
  8458. {
  8459. case type_qstring:
  8460. func = subQStrFXAtom;
  8461. break;
  8462. case type_data:
  8463. func = subDataFXAtom;
  8464. break;
  8465. case type_unicode:
  8466. case type_varunicode:
  8467. func = unicodeSubStrFXAtom;
  8468. break;
  8469. case type_utf8:
  8470. func = utf8SubStrFXAtom;
  8471. break;
  8472. default:
  8473. func = subStrFXAtom;
  8474. break;
  8475. }
  8476. }
  8477. OwnedHqlExpr call = bindFunctionCall(func, args);
  8478. buildExprAssign(ctx, tempTarget, call);
  8479. }
  8480. doneAssign = true;
  8481. }
  8482. if (!doneAssign)
  8483. assign(ctx, target, newBound);
  8484. }
  8485. bool HqlCppTranslator::doBuildExprSpecialSubString(BuildCtx & ctx, SubStringInfo & info, CHqlBoundExpr & tgt)
  8486. {
  8487. unsigned size = info.srcType->getStringLen();
  8488. unsigned fromIndex = info.fixedStart;
  8489. unsigned toIndex = info.fixedEnd;
  8490. //If substring is larger than the source use the default processing.
  8491. if (toIndex <= size)
  8492. {
  8493. CHqlBoundExpr boundSrc;
  8494. buildCachedExpr(ctx, info.src, boundSrc);
  8495. boundSrc.expr.setown(getIndexedElementPointer(boundSrc.expr, fromIndex-1));
  8496. unsigned newLength = fromIndex <= toIndex ? toIndex-(fromIndex-1) : 0;
  8497. ITypeInfo * newType = makeReferenceModifier(getStretchedType(newLength, info.srcType));
  8498. tgt.expr.setown(createValue(no_typetransfer, newType, boundSrc.expr.getClear()));
  8499. if (info.expr->queryType()->getStringLen() != newLength)
  8500. tgt.length.setown(getSizetConstant(newLength));
  8501. return true;
  8502. }
  8503. return false;
  8504. }
  8505. bool HqlCppTranslator::doBuildExprInfiniteSubString(BuildCtx & ctx, SubStringInfo & info, CHqlBoundExpr & tgt)
  8506. {
  8507. CHqlBoundExpr boundSrc;
  8508. info.bindToFrom(*this, ctx);
  8509. buildCachedExpr(ctx, info.src, boundSrc);
  8510. IHqlExpression * from = info.from;
  8511. if (info.fixedStart == 1)
  8512. from = NULL;
  8513. IHqlExpression * start = from ? adjustValue(info.boundFrom.expr, -1) : NULL;
  8514. tgt.expr.setown(getIndexedElementPointer(boundSrc.expr, start));
  8515. //ensure type is no longer infinite length, so same optimization does not happen again...
  8516. ITypeInfo * newType = makeReferenceModifier(getStretchedType(UNKNOWN_LENGTH, tgt.expr->queryType()));
  8517. tgt.expr.setown(createValue(no_typetransfer, newType, tgt.expr.getLink()));
  8518. OwnedHqlExpr length;
  8519. if (start && !isZero(start))
  8520. length.setown(createValue(no_sub, info.boundTo.expr.getLink(), LINK(start)));
  8521. else
  8522. length.setown(info.boundTo.expr.getLink());
  8523. tgt.length.setown(ensureExprType(length, sizetType));
  8524. ::Release(start);
  8525. return true;
  8526. }
  8527. void HqlCppTranslator::doBuildExprAnySubString(BuildCtx & ctx, SubStringInfo & info, CHqlBoundExpr & tgt)
  8528. {
  8529. CHqlBoundExpr boundSource;
  8530. buildCachedExpr(ctx, info.src, boundSource);
  8531. info.bindToFrom(*this, ctx);
  8532. OwnedHqlExpr from;
  8533. if (info.from)
  8534. {
  8535. OwnedHqlExpr start = adjustValue(info.boundFrom.expr, -1);
  8536. if (!isZero(start))
  8537. {
  8538. HqlExprArray args;
  8539. args.append(*LINK(start));
  8540. args.append(*getBoundLength(boundSource));
  8541. OwnedHqlExpr call = bindTranslatedFunctionCall(rtlMinAtom, args);
  8542. call.setown(createTranslated(call));
  8543. CHqlBoundExpr fromVar;
  8544. buildTempExpr(ctx, call, fromVar);
  8545. from.set(fromVar.expr);
  8546. }
  8547. }
  8548. OwnedHqlExpr to;
  8549. if (info.to)
  8550. {
  8551. OwnedHqlExpr toExpr = LINK(info.boundTo.expr);
  8552. if (from)
  8553. {
  8554. HqlExprArray args;
  8555. args.append(*LINK(toExpr));
  8556. args.append(*LINK(from));
  8557. toExpr.setown(bindTranslatedFunctionCall(rtlMaxAtom, args));
  8558. }
  8559. HqlExprArray args;
  8560. args.append(*LINK(toExpr));
  8561. args.append(*getBoundLength(boundSource));
  8562. to.setown(bindTranslatedFunctionCall(rtlMinAtom, args));
  8563. }
  8564. else
  8565. to.setown(getBoundLength(boundSource));
  8566. boundSource.expr.setown(getIndexedElementPointer(boundSource.expr, from));
  8567. ITypeInfo * newType = makeReferenceModifier(info.expr->getType());
  8568. tgt.expr.setown(createValue(no_typetransfer, newType, boundSource.expr.getClear()));
  8569. if (from && !isZero(from))
  8570. tgt.length.setown(createValue(no_sub, LINK(sizetType), LINK(to), LINK(from)));
  8571. else
  8572. tgt.length.set(to);
  8573. }
  8574. void HqlCppTranslator::doBuildExprSubString(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8575. {
  8576. if (expr->queryChild(1)->getOperator() == no_rangecommon)
  8577. throwError(HQLERR_StarRangeOnlyInJoinCondition);
  8578. /* Optimize string[start..end] into a type transfer where appropriate */
  8579. SubStringInfo info(expr);
  8580. if (info.special)
  8581. if (doBuildExprSpecialSubString(ctx, info, tgt))
  8582. return;
  8583. if (info.infiniteString)
  8584. if (doBuildExprInfiniteSubString(ctx, info, tgt))
  8585. return;
  8586. if (expr->hasProperty(quickAtom))
  8587. {
  8588. doBuildExprAnySubString(ctx, info, tgt);
  8589. return;
  8590. }
  8591. buildTempExpr(ctx, expr, tgt);
  8592. }
  8593. //---------------------------------------------------------------------------
  8594. //-- no_trim --
  8595. void HqlCppTranslator::doBuildAssignTrim(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8596. {
  8597. IHqlExpression * str = expr->queryChild(0);
  8598. _ATOM func;
  8599. bool hasAll = expr->hasProperty(allAtom);
  8600. bool hasLeft = expr->hasProperty(leftAtom);
  8601. bool hasRight = expr->hasProperty(rightAtom);
  8602. if (str->queryType()->getTypeCode() == type_varstring)
  8603. {
  8604. if(hasAll)
  8605. func = trimVAllAtom;
  8606. else if(hasLeft && hasRight)
  8607. func = trimVBothAtom;
  8608. else if(hasLeft)
  8609. func = trimVLeftAtom;
  8610. else
  8611. func = trimVRightAtom;
  8612. }
  8613. else if(str->queryType()->getTypeCode() == type_unicode)
  8614. {
  8615. if(hasAll)
  8616. func = trimUnicodeAllAtom;
  8617. else if(hasLeft && hasRight)
  8618. func = trimUnicodeBothAtom;
  8619. else if(hasLeft)
  8620. func = trimUnicodeLeftAtom;
  8621. else
  8622. func = trimUnicodeRightAtom;
  8623. }
  8624. else if(str->queryType()->getTypeCode() == type_varunicode)
  8625. {
  8626. if(hasAll)
  8627. func = trimVUnicodeAllAtom;
  8628. else if(hasLeft && hasRight)
  8629. func = trimVUnicodeBothAtom;
  8630. else if(hasLeft)
  8631. func = trimVUnicodeLeftAtom;
  8632. else
  8633. func = trimVUnicodeRightAtom;
  8634. }
  8635. else if(str->queryType()->getTypeCode() == type_utf8)
  8636. {
  8637. if(hasAll)
  8638. func = trimUtf8AllAtom;
  8639. else if(hasLeft && hasRight)
  8640. func = trimUtf8BothAtom;
  8641. else if(hasLeft)
  8642. func = trimUtf8LeftAtom;
  8643. else
  8644. func = trimUtf8RightAtom;
  8645. }
  8646. else
  8647. {
  8648. if(hasAll)
  8649. func = trimAllAtom;
  8650. else if(hasLeft && hasRight)
  8651. func = trimBothAtom;
  8652. else if(hasLeft)
  8653. func = trimLeftAtom;
  8654. else
  8655. func = trimRightAtom;
  8656. }
  8657. HqlExprArray args;
  8658. args.append(*LINK(str));
  8659. OwnedHqlExpr call = bindFunctionCall(func, args);
  8660. buildExprAssign(ctx, target, call);
  8661. }
  8662. void HqlCppTranslator::doBuildExprTrim(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8663. {
  8664. // MORE - support LEFT,RIGHT,ALL attributes
  8665. CHqlBoundExpr bound;
  8666. buildSimpleExpr(ctx, expr->queryChild(0), bound);
  8667. HqlExprArray args;
  8668. _ATOM func;
  8669. OwnedHqlExpr str = getElementPointer(bound.expr);
  8670. bool hasAll = expr->hasProperty(allAtom);
  8671. bool hasLeft = expr->hasProperty(leftAtom);
  8672. bool hasRight = expr->hasProperty(rightAtom);
  8673. type_t btc = bound.expr->queryType()->getTypeCode();
  8674. if(hasAll || hasLeft)
  8675. {
  8676. if (btc == type_varstring)
  8677. {
  8678. if(hasAll) {
  8679. func = trimVAllAtom;
  8680. }
  8681. else if(hasLeft && hasRight) {
  8682. func = trimVBothAtom;
  8683. }
  8684. else {
  8685. func = trimVLeftAtom;
  8686. }
  8687. }
  8688. else if (btc == type_unicode)
  8689. {
  8690. if(hasAll) {
  8691. func = trimUnicodeAllAtom;
  8692. }
  8693. else if(hasLeft && hasRight) {
  8694. func = trimUnicodeBothAtom;
  8695. }
  8696. else {
  8697. func = trimUnicodeLeftAtom;
  8698. }
  8699. }
  8700. else if (btc == type_varunicode)
  8701. {
  8702. if(hasAll) {
  8703. func = trimVUnicodeAllAtom;
  8704. }
  8705. else if(hasLeft && hasRight) {
  8706. func = trimVUnicodeBothAtom;
  8707. }
  8708. else {
  8709. func = trimVUnicodeLeftAtom;
  8710. }
  8711. }
  8712. else if (btc == type_utf8)
  8713. {
  8714. if(hasAll) {
  8715. func = trimUtf8AllAtom;
  8716. }
  8717. else if(hasLeft && hasRight) {
  8718. func = trimUtf8BothAtom;
  8719. }
  8720. else {
  8721. func = trimUtf8LeftAtom;
  8722. }
  8723. }
  8724. else
  8725. {
  8726. if(hasAll) {
  8727. func = trimAllAtom;
  8728. }
  8729. else if(hasLeft && hasRight) {
  8730. func = trimBothAtom;
  8731. }
  8732. else {
  8733. func = trimLeftAtom;
  8734. }
  8735. }
  8736. args.append(*bound.getTranslatedExpr());
  8737. OwnedHqlExpr call = bindFunctionCall(func, args);
  8738. buildExpr(ctx, call, tgt);
  8739. }
  8740. else {
  8741. if (btc == type_varstring)
  8742. {
  8743. args.append(*LINK(str));
  8744. func = trimVStrLenAtom;
  8745. }
  8746. else if (btc == type_unicode)
  8747. {
  8748. args.append(*getBoundLength(bound));
  8749. args.append(*LINK(str));
  8750. func = trimUnicodeStrLenAtom;
  8751. }
  8752. else if (btc == type_varunicode)
  8753. {
  8754. args.append(*LINK(str));
  8755. func = trimVUnicodeStrLenAtom;
  8756. }
  8757. else if (btc == type_utf8)
  8758. {
  8759. args.append(*getBoundLength(bound));
  8760. args.append(*LINK(str));
  8761. func = trimUtf8StrLenAtom;
  8762. }
  8763. else
  8764. {
  8765. args.append(*getBoundLength(bound));
  8766. args.append(*LINK(str));
  8767. func = trimStrLenAtom;
  8768. }
  8769. tgt.length.setown(bindTranslatedFunctionCall(func, args));
  8770. tgt.expr.set(str);
  8771. }
  8772. }
  8773. //---------------------------------------------------------------------------
  8774. void HqlCppTranslator::doBuildExprIsValid(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8775. {
  8776. IHqlExpression * const value = expr->queryChild(0);
  8777. HqlExprArray args;
  8778. ITypeInfo * type = value->queryType();
  8779. assertex(type);
  8780. if (type->getTypeCode() == type_alien)
  8781. {
  8782. IHqlAlienTypeInfo * alien = queryAlienType(type);
  8783. IHqlExpression * isValidFunction = alien->queryFunction(getIsValidAtom);
  8784. if (isValidFunction)
  8785. {
  8786. CHqlBoundExpr bound;
  8787. buildAddress(ctx, value, bound);
  8788. OwnedITypeInfo physicalType = alien->getPhysicalType();
  8789. if (!isTypePassedByAddress(physicalType))
  8790. bound.expr.setown(createValue(no_deref, makeReferenceModifier(LINK(physicalType)), LINK(bound.expr)));
  8791. HqlExprArray args;
  8792. args.append(*bound.getTranslatedExpr());
  8793. OwnedHqlExpr test = createBoundFunction(NULL, isValidFunction, args, NULL, true);
  8794. buildExpr(ctx, test, tgt);
  8795. return;
  8796. }
  8797. else
  8798. type = alien->queryLogicalType();
  8799. }
  8800. CHqlBoundExpr bound;
  8801. buildExpr(ctx, value, bound);
  8802. ensureHasAddress(ctx, bound);
  8803. OwnedHqlExpr address = getPointer(bound.expr);
  8804. switch (type->getTypeCode())
  8805. {
  8806. case type_decimal:
  8807. args.append(*createConstant(type->isSigned()));
  8808. args.append(*getSizetConstant(type->getDigits()));
  8809. args.append(*address.getLink());
  8810. tgt.expr.setown(bindTranslatedFunctionCall(DecValidAtom, args));
  8811. break;
  8812. case type_real:
  8813. args.append(*getSizetConstant(type->getSize()));
  8814. args.append(*address.getLink());
  8815. tgt.expr.setown(bindTranslatedFunctionCall(validRealAtom, args));
  8816. break;
  8817. default:
  8818. tgt.expr.set(queryBoolExpr(true));
  8819. break;
  8820. }
  8821. }
  8822. IHqlExpression * HqlCppTranslator::getConstWuid(IHqlExpression * expr)
  8823. {
  8824. SCMStringBuffer out;
  8825. wu()->getWuid(out);
  8826. OwnedHqlExpr wuid = createConstant(out.str());
  8827. return ensureExprType(wuid, expr->queryType());
  8828. }
  8829. void HqlCppTranslator::doBuildAssignWuid(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8830. {
  8831. HqlExprArray args;
  8832. OwnedHqlExpr call = bindFunctionCall(getWuidAtom, args);
  8833. buildExprAssign(ctx, target, call);
  8834. }
  8835. void HqlCppTranslator::doBuildExprWuid(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8836. {
  8837. HqlExprArray args;
  8838. OwnedHqlExpr call = bindFunctionCall(getWuidAtom, args);
  8839. buildTempExpr(ctx, call, tgt);
  8840. }
  8841. IHqlExpression * HqlCppTranslator::cvtGetEnvToCall(IHqlExpression * expr)
  8842. {
  8843. IHqlExpression * dft = queryRealChild(expr, 1);
  8844. HqlExprArray args;
  8845. args.append(*LINK(expr->queryChild(0)));
  8846. if (dft)
  8847. args.append(*LINK(dft));
  8848. else
  8849. args.append(*createConstant(createStringValue((const char *)NULL, 0U)));
  8850. return bindFunctionCall(getEnvAtom, args);
  8851. }
  8852. //---------------------------------------------------------------------------
  8853. void HqlCppTranslator::doBuildAssignToFromUnicode(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8854. {
  8855. HqlExprArray args;
  8856. if(!target.isFixedSize())
  8857. {
  8858. args.append(*LINK(expr->queryChild(0)));
  8859. args.append(*foldHqlExpression(expr->queryChild(1)));
  8860. OwnedHqlExpr call = bindFunctionCall((expr->getOperator() == no_fromunicode) ? unicode2CodepageXAtom : codepage2UnicodeXAtom, args);
  8861. buildExprAssign(ctx, target, call);
  8862. }
  8863. else
  8864. {
  8865. args.append(*createTranslated(target.expr));
  8866. args.append(*LINK(expr->queryChild(0)));
  8867. args.append(*foldHqlExpression(expr->queryChild(1)));
  8868. OwnedHqlExpr call = bindFunctionCall((expr->getOperator() == no_fromunicode) ? unicode2CodepageAtom : codepage2UnicodeAtom, args);
  8869. buildStmt(ctx, call);
  8870. }
  8871. }
  8872. void HqlCppTranslator::doBuildExprToFromUnicode(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8873. {
  8874. HqlExprArray args;
  8875. args.append(*LINK(expr->queryChild(0)));
  8876. args.append(*foldHqlExpression(expr->queryChild(1)));
  8877. OwnedHqlExpr call = bindFunctionCall((expr->getOperator() == no_fromunicode) ? unicode2CodepageXAtom : codepage2UnicodeXAtom, args);
  8878. buildExpr(ctx, call, tgt);
  8879. }
  8880. //---------------------------------------------------------------------------
  8881. void HqlCppTranslator::doBuildExprKeyUnicode(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  8882. {
  8883. HqlExprArray args;
  8884. args.append(*LINK(expr->queryChild(0)));
  8885. args.append(*LINK(expr->queryChild(1)));
  8886. args.append(*LINK(expr->queryChild(2)));
  8887. OwnedHqlExpr call = bindFunctionCall(keyUnicodeStrengthXAtom, args);
  8888. buildExpr(ctx, call, tgt);
  8889. }
  8890. //---------------------------------------------------------------------------
  8891. void HqlCppTranslator::doBuildAssignWhich(BuildCtx & ctx, const CHqlBoundTarget & target, IHqlExpression * expr)
  8892. {
  8893. BuildCtx whichCtx(ctx);
  8894. unsigned max = expr->numChildren();
  8895. unsigned idx;
  8896. bool invert = (expr->getOperator() == no_rejected);
  8897. for (idx = 0; idx < max; idx++)
  8898. {
  8899. IHqlExpression * cur = expr->queryChild(idx);
  8900. CHqlBoundExpr bound;
  8901. if (invert)
  8902. {
  8903. OwnedHqlExpr inverse = getInverse(cur);
  8904. buildExpr(whichCtx, inverse, bound);
  8905. }
  8906. else
  8907. buildExpr(whichCtx, cur, bound);
  8908. IHqlStmt * stmt = whichCtx.addFilter(bound.expr);
  8909. OwnedHqlExpr value = createConstant(target.queryType()->castFrom(false, idx+1));
  8910. assignBound(whichCtx, target, value);
  8911. whichCtx.selectElse(stmt);
  8912. }
  8913. assignBound(whichCtx, target, queryZero());
  8914. }
  8915. //---------------------------------------------------------------------------
  8916. void HqlCppTranslator::assignBound(BuildCtx & ctx, const CHqlBoundTarget & lhs, IHqlExpression * rhs)
  8917. {
  8918. CHqlBoundExpr bound;
  8919. bound.expr.set(rhs);
  8920. assign(ctx, lhs, bound);
  8921. }
  8922. void HqlCppTranslator::assignBoundToTemp(BuildCtx & ctx, IHqlExpression * lhs, IHqlExpression * rhs)
  8923. {
  8924. CHqlBoundExpr bound;
  8925. CHqlBoundTarget target;
  8926. bound.expr.set(rhs);
  8927. target.expr.set(lhs);
  8928. assign(ctx, target, bound);
  8929. }
  8930. void HqlCppTranslator::assign(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & rhs)
  8931. {
  8932. if (!target.isFixedSize())
  8933. {
  8934. assignCastUnknownLength(ctx, target, rhs);
  8935. return;
  8936. }
  8937. IHqlExpression * lhs = target.expr;
  8938. ITypeInfo * lType = lhs->queryType()->queryPromotedType();
  8939. if (!isSameBasicType(lType, rhs.expr->queryType()->queryPromotedType()))
  8940. assignAndCast(ctx, target, rhs);
  8941. else
  8942. {
  8943. switch (lType->getTypeCode())
  8944. {
  8945. case type_decimal:
  8946. if (isPushed(rhs))
  8947. {
  8948. _ATOM funcName = lType->isSigned() ? DecPopDecimalAtom : DecPopUDecimalAtom;
  8949. HqlExprArray args;
  8950. args.append(*getPointer(lhs));
  8951. args.append(*getSizetConstant(lType->getSize()));
  8952. args.append(*getSizetConstant(lType->getPrecision()));
  8953. callProcedure(ctx, funcName, args);
  8954. return;
  8955. }
  8956. buildBlockCopy(ctx, lhs, rhs);
  8957. return;
  8958. case type_string:
  8959. {
  8960. if (lType->getSize() == 1 && !options.peephole)
  8961. {
  8962. OwnedHqlExpr l1 = getFirstCharacter(lhs);
  8963. OwnedHqlExpr r1 = getFirstCharacter(rhs.expr);
  8964. ctx.addAssign(l1, r1);
  8965. }
  8966. else
  8967. buildBlockCopy(ctx, lhs, rhs);
  8968. break;
  8969. }
  8970. //fall through...
  8971. case type_unicode:
  8972. case type_data:
  8973. case type_qstring:
  8974. case type_utf8:
  8975. {
  8976. buildBlockCopy(ctx, lhs, rhs);
  8977. break;
  8978. }
  8979. case type_varstring:
  8980. {
  8981. HqlExprArray args;
  8982. args.append(*getElementPointer(lhs));
  8983. args.append(*getElementPointer(rhs.expr));
  8984. callProcedure(ctx, strcpyAtom, args);
  8985. break;
  8986. }
  8987. case type_varunicode:
  8988. {
  8989. HqlExprArray args;
  8990. args.append(*getElementPointer(lhs));
  8991. args.append(*getElementPointer(rhs.expr));
  8992. callProcedure(ctx, unicodeStrcpyAtom, args);
  8993. break;
  8994. }
  8995. case type_row:
  8996. {
  8997. if (hasWrapperModifier(target.queryType()))
  8998. {
  8999. //I can't think of any situation where this isn't true....
  9000. assertex(hasLinkCountedModifier(rhs.expr));
  9001. StringBuffer assignText;
  9002. generateExprCpp(assignText, lhs).append(".set(");
  9003. generateExprCpp(assignText, rhs.expr).append(");");
  9004. ctx.addQuoted(assignText);
  9005. //Could generate the following instead
  9006. //ctx.addAssign(lhs, no_link(rhs.expr));
  9007. //And post-optimize to the above.
  9008. }
  9009. else
  9010. ctx.addAssign(lhs, rhs.expr);
  9011. break;
  9012. }
  9013. default:
  9014. ctx.addAssign(lhs, rhs.expr);
  9015. break;
  9016. }
  9017. }
  9018. }
  9019. void HqlCppTranslator::doStringTranslation(BuildCtx & ctx, ICharsetInfo * tgtset, ICharsetInfo * srcset, unsigned tgtlen, IHqlExpression * srclen, IHqlExpression * target, IHqlExpression * src)
  9020. {
  9021. HqlExprArray args;
  9022. ITranslationInfo * translator = queryDefaultTranslation(tgtset, srcset);
  9023. if (translator)
  9024. {
  9025. _ATOM func = createIdentifierAtom(translator->queryRtlFunction());
  9026. args.append(*getSizetConstant(tgtlen));
  9027. args.append(*getElementPointer(target));
  9028. args.append(*LINK(srclen));
  9029. args.append(*getElementPointer(src));
  9030. callProcedure(ctx, func, args);
  9031. }
  9032. }
  9033. void HqlCppTranslator::assignSwapInt(BuildCtx & ctx, ITypeInfo * to, const CHqlBoundTarget & target, CHqlBoundExpr & pure)
  9034. {
  9035. switch (pure.expr->getOperator())
  9036. {
  9037. case no_deref:
  9038. case no_variable:
  9039. break;
  9040. default:
  9041. {
  9042. OwnedHqlExpr translated = pure.getTranslatedExpr();
  9043. pure.clear();
  9044. buildTempExpr(ctx, translated, pure);
  9045. break;
  9046. }
  9047. }
  9048. ITypeInfo * from = pure.expr->queryType();
  9049. unsigned copySize = to->getSize();
  9050. assertex(copySize == from->getSize());
  9051. IHqlExpression * address = getRawAddress(pure.expr);
  9052. switch (copySize)
  9053. {
  9054. case 1:
  9055. ctx.addAssign(target.expr, pure.expr);
  9056. break;
  9057. default:
  9058. {
  9059. HqlExprArray args;
  9060. args.append(*address);
  9061. OwnedHqlExpr call = bindTranslatedFunctionCall(reverseIntAtom[copySize][to->isSigned()], args);
  9062. ctx.addAssign(target.expr, call);
  9063. break;
  9064. }
  9065. }
  9066. }
  9067. void HqlCppTranslator::throwCannotCast(ITypeInfo * from, ITypeInfo * to)
  9068. {
  9069. StringBuffer fromText, toText;
  9070. getFriendlyTypeStr(from, fromText);
  9071. getFriendlyTypeStr(to, toText);
  9072. throwError2(HQLERR_CastXNotImplemented, fromText.str(), toText.str());
  9073. }
  9074. void HqlCppTranslator::assignAndCast(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & pure)
  9075. {
  9076. if (!target.isFixedSize())
  9077. {
  9078. assignCastUnknownLength(ctx, target, pure);
  9079. return;
  9080. }
  9081. ITypeInfo * to = target.queryType()->queryPromotedType();
  9082. if ((pure.expr->getOperator() == no_constant) && options.foldConstantCast &&
  9083. ((options.inlineStringThreshold == 0) || (to->getSize() <= options.inlineStringThreshold)))
  9084. {
  9085. OwnedHqlExpr cast = getCastExpr(to, pure.expr);
  9086. if (cast)
  9087. {
  9088. assignBound(ctx, target, cast);
  9089. return;
  9090. }
  9091. }
  9092. //NB: Does not include variable length return types....
  9093. ITypeInfo * from = (pure.expr->queryType()->queryPromotedType());
  9094. type_t toType = to->getTypeCode();
  9095. type_t fromType = from->getTypeCode();
  9096. unsigned toSize = to->getSize();
  9097. IHqlExpression * targetVar = target.expr;
  9098. HqlExprArray args;
  9099. assertex(targetVar);
  9100. assertex(toSize != UNKNOWN_LENGTH);
  9101. switch(toType)
  9102. {
  9103. case type_qstring:
  9104. switch (fromType)
  9105. {
  9106. case type_qstring:
  9107. {
  9108. unsigned srcsize = from->getSize();
  9109. if (!pure.length && (srcsize == toSize))
  9110. {
  9111. //memcpy(tgt, src, srclen)
  9112. args.append(*getElementPointer(targetVar));
  9113. args.append(*getElementPointer(pure.expr));
  9114. args.append(*getSizetConstant(toSize));
  9115. callProcedure(ctx, memcpyAtom, args);
  9116. }
  9117. else
  9118. {
  9119. args.append(*getSizetConstant(to->getStringLen()));
  9120. args.append(*getElementPointer(targetVar));
  9121. args.append(*getBoundLength(pure));
  9122. args.append(*getElementPointer(pure.expr));
  9123. callProcedure(ctx, qstrToQStrAtom, args);
  9124. }
  9125. break;
  9126. }
  9127. case type_data:
  9128. case type_varstring:
  9129. case type_string:
  9130. {
  9131. if(!queryDefaultTranslation(to->queryCharset(), from->queryCharset()))
  9132. {
  9133. args.append(*getSizetConstant(to->getStringLen()));
  9134. args.append(*getElementPointer(targetVar));
  9135. args.append(*getBoundLength(pure));
  9136. args.append(*getElementPointer(pure.expr));
  9137. callProcedure(ctx, strToQStrAtom, args);
  9138. break;
  9139. }
  9140. //fall through
  9141. }
  9142. default:
  9143. //Need to go via a temporary string.
  9144. OwnedHqlExpr temp = pure.getTranslatedExpr();
  9145. buildExprAssignViaString(ctx, target, temp, to->getStringLen());
  9146. return;
  9147. }
  9148. break;
  9149. case type_data:
  9150. case type_string:
  9151. case type_varstring:
  9152. {
  9153. unsigned srclen = from->getSize();
  9154. ICharsetInfo * srcset = NULL;
  9155. ICharsetInfo * tgtset = to->queryCharset();
  9156. switch (fromType)
  9157. {
  9158. case type_data:
  9159. case type_string:
  9160. case type_varstring:
  9161. {
  9162. srcset = from->queryCharset();
  9163. OwnedHqlExpr boundLen = getBoundLength(pure);
  9164. if ((srcset == tgtset) || (toType == type_data) || (fromType == type_data))
  9165. {
  9166. bool doDefault = true;
  9167. if (boundLen->queryValue())
  9168. {
  9169. unsigned srclen = (unsigned)boundLen->queryValue()->getIntValue();
  9170. if (srclen >= toSize && toType != type_varstring)
  9171. {
  9172. if (srclen > toSize)
  9173. srclen = toSize;
  9174. //memcpy(tgt, src, srclen)
  9175. args.append(*getElementPointer(targetVar));
  9176. args.append(*getElementPointer(pure.expr));
  9177. args.append(*getSizetConstant(srclen));
  9178. callProcedure(ctx, memcpyAtom, args);
  9179. doDefault = false;
  9180. }
  9181. }
  9182. if (doDefault)
  9183. {
  9184. if (fromType == type_varstring)
  9185. {
  9186. _ATOM func;
  9187. switch (toType)
  9188. {
  9189. case type_varstring: func = vstr2VStrAtom; break;
  9190. case type_string: func = vstr2StrAtom; break;
  9191. case type_data: func = vstr2DataAtom; break;
  9192. default: UNIMPLEMENTED;
  9193. }
  9194. if ((toSize < srclen) || (srclen==UNKNOWN_LENGTH) || (toType != type_varstring))
  9195. {
  9196. args.append(*getSizetConstant(toSize));
  9197. args.append(*getElementPointer(targetVar));
  9198. args.append(*getElementPointer(pure.expr));
  9199. callProcedure(ctx, func, args);
  9200. }
  9201. else
  9202. {
  9203. //strcpy(tgt, src);
  9204. args.append(*getElementPointer(targetVar));
  9205. args.append(*getElementPointer(pure.expr));
  9206. callProcedure(ctx, strcpyAtom, args);
  9207. }
  9208. }
  9209. else
  9210. {
  9211. _ATOM func;
  9212. switch (toType)
  9213. {
  9214. case type_data:
  9215. func = str2DataAtom;
  9216. break;
  9217. case type_varstring:
  9218. func = str2VStrAtom;
  9219. break;
  9220. case type_string:
  9221. func = (srcset->queryName() == ebcdicAtom) ? estr2EStrAtom : str2StrAtom;
  9222. break;
  9223. }
  9224. args.append(*getSizetConstant(toSize));
  9225. args.append(*getElementPointer(targetVar));
  9226. args.append(*LINK(boundLen));
  9227. args.append(*getElementPointer(pure.expr));
  9228. callProcedure(ctx, func, args);
  9229. }
  9230. }
  9231. }
  9232. else
  9233. {
  9234. if ((from->getSize() == INFINITE_LENGTH) && !pure.length)
  9235. throwError(HQLERR_CastInfiniteString);
  9236. IHqlExpression * srclen;
  9237. if (toType == type_varstring)
  9238. {
  9239. srclen = getSizetConstant(toSize);
  9240. args.append(*srclen);
  9241. args.append(*getElementPointer(targetVar));
  9242. args.append(*LINK(boundLen));
  9243. args.append(*getElementPointer(pure.expr));
  9244. callProcedure(ctx, estr2VStrAtom, args);
  9245. }
  9246. else
  9247. doStringTranslation(ctx, tgtset, srcset, toSize, boundLen, targetVar, pure.expr);
  9248. }
  9249. }
  9250. break;
  9251. case type_qstring:
  9252. if (queryDefaultTranslation(tgtset, from->queryCharset()))
  9253. {
  9254. OwnedHqlExpr temp = pure.getTranslatedExpr();
  9255. buildExprAssignViaString(ctx, target, temp, to->getStringLen());
  9256. }
  9257. else
  9258. {
  9259. _ATOM func;
  9260. switch (toType)
  9261. {
  9262. case type_varstring: func = qstr2VStrAtom; break;
  9263. case type_string: func = qstr2StrAtom; break;
  9264. case type_data: func = qstr2DataAtom; break;
  9265. }
  9266. args.append(*getSizetConstant(toSize));
  9267. args.append(*getElementPointer(targetVar));
  9268. args.append(*getBoundLength(pure));
  9269. args.append(*getElementPointer(pure.expr));
  9270. callProcedure(ctx, func, args);
  9271. }
  9272. break;
  9273. case type_unicode:
  9274. case type_varunicode:
  9275. {
  9276. _ATOM func;
  9277. switch(toType)
  9278. {
  9279. case type_data:
  9280. func = (fromType == type_varunicode) ? vunicode2DataAtom : unicode2DataAtom;
  9281. break;
  9282. case type_string:
  9283. func = (fromType == type_varunicode) ? vunicode2CodepageAtom : unicode2CodepageAtom;
  9284. break;
  9285. case type_varstring:
  9286. func = (fromType == type_varunicode) ? vunicode2VCodepageAtom : unicode2VCodepageAtom;
  9287. break;
  9288. }
  9289. args.append(*getSizetConstant(toSize));
  9290. args.append(*getElementPointer(targetVar));
  9291. if(fromType != type_varunicode)
  9292. args.append(*getBoundLength(pure));
  9293. args.append(*getElementPointer(pure.expr));
  9294. if(toType != type_data)
  9295. args.append(*createConstant(to->queryCharset()->queryCodepageName()));
  9296. callProcedure(ctx, func, args);
  9297. }
  9298. break;
  9299. case type_utf8:
  9300. {
  9301. _ATOM func;
  9302. switch(toType)
  9303. {
  9304. case type_data:
  9305. func = utf82DataAtom;
  9306. break;
  9307. case type_string:
  9308. func = utf82CodepageAtom;
  9309. break;
  9310. case type_varstring:
  9311. OwnedHqlExpr temp = pure.getTranslatedExpr();
  9312. buildExprAssignViaString(ctx, target, temp, to->getStringLen());
  9313. return;
  9314. }
  9315. args.append(*getSizetConstant(toSize));
  9316. args.append(*getElementPointer(targetVar));
  9317. args.append(*getBoundLength(pure));
  9318. args.append(*getElementPointer(pure.expr));
  9319. if(toType != type_data)
  9320. args.append(*createConstant(to->queryCharset()->queryCodepageName()));
  9321. callProcedure(ctx, func, args);
  9322. }
  9323. break;
  9324. case type_swapint:
  9325. {
  9326. CHqlBoundExpr recast;
  9327. ITypeInfo * tempType = makeIntType(srclen, from->isSigned());
  9328. OwnedHqlExpr translated = createValue(no_implicitcast, tempType, pure.getTranslatedExpr());
  9329. buildExpr(ctx, translated, recast);
  9330. assignAndCast(ctx, target, recast);
  9331. return;
  9332. }
  9333. case type_int:
  9334. case type_packedint:
  9335. {
  9336. //l2an4(toSize, tgt, expr);
  9337. _ATOM funcName;
  9338. if (from->isSigned())
  9339. {
  9340. if (toType != type_varstring)
  9341. funcName = (srclen > 4 ? ls82anAtom : ls42anAtom);
  9342. else
  9343. funcName = (srclen > 4 ? ls82vnAtom : ls42vnAtom);
  9344. }
  9345. else
  9346. {
  9347. if (toType != type_varstring)
  9348. funcName = (srclen > 4 ? l82anAtom : l42anAtom);
  9349. else
  9350. funcName = (srclen > 4 ? l82vnAtom : l42vnAtom);
  9351. }
  9352. IHqlExpression * strlen = getSizetConstant(toSize);
  9353. args.append(*strlen);
  9354. args.append(*getElementPointer(targetVar));
  9355. args.append(*LINK(pure.expr));
  9356. callProcedure(ctx, funcName, args);
  9357. if (toType != type_data)
  9358. {
  9359. Owned<ICharsetInfo> charset = getCharset(asciiAtom);
  9360. doStringTranslation(ctx, tgtset, charset, toSize, strlen, targetVar, targetVar);
  9361. }
  9362. break;
  9363. }
  9364. case type_void:
  9365. if (pure.expr->getOperator() != no_decimalstack)
  9366. {
  9367. throwCannotCast(from, to);
  9368. break;
  9369. }
  9370. //fall through
  9371. case type_decimal:
  9372. {
  9373. ensurePushed(ctx, pure);
  9374. args.append(*getSizetConstant(toSize));
  9375. OwnedHqlExpr sp = getElementPointer(targetVar);
  9376. args.append(*ensureIndexable(sp));
  9377. _ATOM func;
  9378. switch (toType)
  9379. {
  9380. case type_string: func = DecPopStringAtom; break;
  9381. case type_data: func = DecPopStringAtom; break;
  9382. case type_varstring: func = DecPopVStringAtom; break;
  9383. }
  9384. callProcedure(ctx, func, args);
  9385. break;
  9386. }
  9387. case type_enumerated:
  9388. throwCannotCast(from, to);
  9389. break;
  9390. case type_boolean:
  9391. {
  9392. _ATOM func = (toType == type_varstring) ? bool2VStrAtom : (toType == type_data) ? bool2DataAtom : bool2StrAtom;
  9393. args.append(*getSizetConstant(toSize));
  9394. args.append(*getElementPointer(targetVar));
  9395. args.append(*pure.expr.getLink());
  9396. callProcedure(ctx, func, args);
  9397. break;
  9398. }
  9399. case type_real:
  9400. {
  9401. IHqlExpression * strlen = getSizetConstant(toSize);
  9402. args.append(*strlen);
  9403. args.append(*getElementPointer(targetVar));
  9404. args.append(*pure.expr.getLink());
  9405. _ATOM func = (toType == type_varstring) ? f2vnAtom : f2anAtom;
  9406. callProcedure(ctx, func, args);
  9407. if (toType != type_data)
  9408. {
  9409. Owned<ICharsetInfo> charset = getCharset(asciiAtom);
  9410. doStringTranslation(ctx, tgtset, charset, toSize, strlen, targetVar, targetVar);
  9411. }
  9412. }
  9413. break;
  9414. default:
  9415. throwCannotCast(from, to);
  9416. break;
  9417. }
  9418. }
  9419. break;
  9420. case type_unicode:
  9421. case type_varunicode:
  9422. switch (fromType)
  9423. {
  9424. case type_unicode:
  9425. case type_varunicode:
  9426. case type_data:
  9427. case type_string:
  9428. case type_varstring:
  9429. case type_utf8:
  9430. {
  9431. _ATOM func;
  9432. switch(fromType)
  9433. {
  9434. case type_unicode:
  9435. func = (toType == type_varunicode) ? unicode2VUnicodeAtom : unicode2UnicodeAtom;
  9436. break;
  9437. case type_varunicode:
  9438. func = (toType == type_varunicode) ? vunicode2VUnicodeAtom : vunicode2UnicodeAtom;
  9439. break;
  9440. case type_data:
  9441. pure.expr.setown(createValue(no_implicitcast, makeReferenceModifier(makeStringType(from->getStringLen(), NULL)), LINK(pure.expr)));
  9442. func = (toType == type_varunicode) ? codepage2VUnicodeAtom : codepage2UnicodeAtom;
  9443. break;
  9444. case type_string:
  9445. func = (toType == type_varunicode) ? codepage2VUnicodeAtom : codepage2UnicodeAtom;
  9446. break;
  9447. case type_varstring:
  9448. func = (toType == type_varunicode) ? vcodepage2VUnicodeAtom : vcodepage2UnicodeAtom;
  9449. break;
  9450. case type_utf8:
  9451. if (toType == type_varunicode)
  9452. {
  9453. OwnedHqlExpr temp = pure.getTranslatedExpr();
  9454. OwnedITypeInfo type = makeUnicodeType(to->getStringLen(), NULL);
  9455. buildExprAssignViaType(ctx, target, temp, type);
  9456. return;
  9457. }
  9458. func = utf82UnicodeAtom;
  9459. break;
  9460. }
  9461. args.append(*getSizetConstant(toSize/2));
  9462. args.append(*getElementPointer(targetVar));
  9463. if((fromType != type_varunicode) && (fromType != type_varstring))
  9464. args.append(*getBoundLength(pure));
  9465. args.append(*getElementPointer(pure.expr));
  9466. if((fromType == type_data) || (fromType == type_string) || (fromType == type_varstring))
  9467. args.append(*createConstant(from->queryCharset()->queryCodepageName()));
  9468. callProcedure(ctx, func, args);
  9469. break;
  9470. }
  9471. default:
  9472. OwnedHqlExpr temp = pure.getTranslatedExpr();
  9473. buildExprAssignViaString(ctx, target, temp, to->getStringLen());
  9474. return;
  9475. }
  9476. break;
  9477. case type_utf8:
  9478. switch (fromType)
  9479. {
  9480. case type_unicode:
  9481. case type_varunicode:
  9482. case type_data:
  9483. case type_string:
  9484. case type_varstring:
  9485. case type_utf8:
  9486. {
  9487. _ATOM func;
  9488. switch(fromType)
  9489. {
  9490. case type_unicode:
  9491. case type_varunicode:
  9492. func = unicodeToUtf8Atom;
  9493. break;
  9494. case type_utf8:
  9495. func = utf8ToUtf8Atom;
  9496. break;
  9497. case type_data:
  9498. case type_string:
  9499. case type_varstring:
  9500. func = codepageToUtf8Atom;
  9501. break;
  9502. }
  9503. args.append(*getSizetConstant(toSize/4));
  9504. args.append(*getElementPointer(targetVar));
  9505. args.append(*getBoundLength(pure));
  9506. args.append(*getElementPointer(pure.expr));
  9507. if((fromType == type_data) || (fromType == type_string) || (fromType == type_varstring))
  9508. args.append(*createConstant(from->queryCharset()->queryCodepageName()));
  9509. callProcedure(ctx, func, args);
  9510. break;
  9511. }
  9512. default:
  9513. OwnedHqlExpr temp = pure.getTranslatedExpr();
  9514. buildExprAssignViaString(ctx, target, temp, to->getStringLen());
  9515. return;
  9516. }
  9517. break;
  9518. case type_decimal:
  9519. {
  9520. CHqlBoundExpr cast;
  9521. doBuildExprCast(ctx, to, pure, cast);
  9522. ensurePushed(ctx, cast);
  9523. _ATOM funcName = to->isSigned() ? DecPopDecimalAtom : DecPopUDecimalAtom;
  9524. args.append(*getPointer(target.expr));
  9525. args.append(*getSizetConstant(to->getSize()));
  9526. args.append(*getSizetConstant(to->getPrecision()));
  9527. callProcedure(ctx, funcName, args);
  9528. }
  9529. break;
  9530. case type_swapint:
  9531. {
  9532. unsigned fromSize = from->getSize();
  9533. if (fromType == type_int)
  9534. {
  9535. if (fromSize != toSize)
  9536. {
  9537. Owned<ITypeInfo> tempType = makeIntType(toSize, from->isSigned());
  9538. pure.expr.setown(ensureExprType(pure.expr, tempType));
  9539. }
  9540. if (toSize != 1)
  9541. {
  9542. assignSwapInt(ctx, to, target, pure);
  9543. return;
  9544. }
  9545. }
  9546. CHqlBoundExpr cast;
  9547. doBuildExprCast(ctx, to, pure, cast);
  9548. ctx.addAssign(target.expr, cast.expr);
  9549. }
  9550. break;
  9551. case type_int:
  9552. case type_packedint:
  9553. {
  9554. unsigned fromSize = from->getSize();
  9555. if ((fromType == type_swapint) && !((fromSize == 1) && (toSize == 1)))
  9556. {
  9557. if (fromSize != toSize)
  9558. {
  9559. CHqlBoundExpr tempInt;
  9560. OwnedITypeInfo tempType = makeIntType(fromSize, from->isSigned());
  9561. doBuildCastViaTemp(ctx, tempType, pure, tempInt);
  9562. CHqlBoundExpr cast;
  9563. doBuildExprCast(ctx, to, tempInt, cast);
  9564. ctx.addAssign(target.expr, cast.expr);
  9565. }
  9566. else
  9567. assignSwapInt(ctx, to, target, pure);
  9568. return;
  9569. }
  9570. }
  9571. //fall through
  9572. case type_boolean:
  9573. case type_real:
  9574. case type_row:
  9575. case type_pointer:
  9576. {
  9577. CHqlBoundExpr cast;
  9578. doBuildExprCast(ctx, to, pure, cast);
  9579. ctx.addAssign(target.expr, cast.expr);
  9580. }
  9581. break;
  9582. default:
  9583. throwCannotCast(from, to);
  9584. break;
  9585. }
  9586. }
  9587. void HqlCppTranslator::assignCastUnknownLength(BuildCtx & ctx, const CHqlBoundTarget & target, CHqlBoundExpr & pure)
  9588. {
  9589. assertex(!target.isFixedSize());
  9590. // must be dynamically allocated return type
  9591. ITypeInfo * to = target.queryType();
  9592. ITypeInfo * from = pure.expr->queryType();
  9593. type_t toType = to->getTypeCode();
  9594. type_t fromType = from->getTypeCode();
  9595. IHqlExpression * codepageParam = 0;
  9596. HqlExprArray args;
  9597. _ATOM funcName = NULL;
  9598. // assertex(target.length && target.pointer || to->getTypeCode() == type_varstring || to->getTypeCode() == type_varunicode);
  9599. switch (toType)
  9600. {
  9601. case type_qstring:
  9602. {
  9603. switch (fromType)
  9604. {
  9605. case type_qstring:
  9606. funcName = qstrToQStrXAtom;
  9607. break;
  9608. case type_string:
  9609. case type_data:
  9610. case type_varstring:
  9611. if(!queryDefaultTranslation(to->queryCharset(), from->queryCharset()))
  9612. {
  9613. funcName = strToQStrXAtom;
  9614. break;
  9615. }
  9616. //fall through
  9617. default:
  9618. CHqlBoundExpr recast;
  9619. ITypeInfo * type = makeStringType(to->getStringLen(), NULL, NULL);
  9620. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9621. buildExpr(ctx, translated, recast);
  9622. assignCastUnknownLength(ctx, target, recast);
  9623. return;
  9624. }
  9625. break;
  9626. }
  9627. case type_string:
  9628. case type_data:
  9629. {
  9630. unsigned srclen = from->getSize();
  9631. switch (fromType)
  9632. {
  9633. case type_data:
  9634. case type_string:
  9635. case type_varstring:
  9636. {
  9637. ICharsetInfo * srcset = from->queryCharset();
  9638. ICharsetInfo * tgtset = to->queryCharset();
  9639. if (to->getTypeCode() == type_data)
  9640. funcName = str2DataXAtom;
  9641. else if ((srcset == tgtset) || (from->getTypeCode() == type_data))
  9642. {
  9643. funcName = str2StrXAtom;
  9644. }
  9645. else
  9646. {
  9647. if ((from->getSize() == INFINITE_LENGTH) && !pure.length)
  9648. throwError(HQLERR_CastInfiniteString);
  9649. ITranslationInfo * translator = queryDefaultTranslation(tgtset, srcset);
  9650. funcName = createIdentifierAtom(translator->queryVarRtlFunction());
  9651. }
  9652. }
  9653. break;
  9654. case type_qstring:
  9655. if(!queryDefaultTranslation(from->queryCharset(), to->queryCharset()))
  9656. {
  9657. funcName = (toType == type_data) ? qstr2DataXAtom : qstr2StrXAtom;
  9658. break;
  9659. }
  9660. else
  9661. {
  9662. CHqlBoundExpr recast;
  9663. ITypeInfo * type = makeStringType(to->getStringLen(), NULL, NULL);
  9664. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9665. buildExpr(ctx, translated, recast);
  9666. assignCastUnknownLength(ctx, target, recast);
  9667. return;
  9668. }
  9669. case type_unicode:
  9670. {
  9671. if(toType == type_data)
  9672. funcName = unicode2DataXAtom;
  9673. else
  9674. {
  9675. funcName = unicode2CodepageXAtom;
  9676. codepageParam = createConstant(to->queryCharset()->queryCodepageName());
  9677. }
  9678. break;
  9679. }
  9680. case type_varunicode:
  9681. {
  9682. if(toType == type_data)
  9683. funcName = vunicode2DataXAtom;
  9684. else
  9685. {
  9686. funcName = vunicode2CodepageXAtom;
  9687. codepageParam = createConstant(to->queryCharset()->queryCodepageName());
  9688. }
  9689. break;
  9690. }
  9691. case type_utf8:
  9692. {
  9693. if(toType == type_data)
  9694. funcName = utf82DataXAtom;
  9695. else
  9696. {
  9697. funcName = utf82CodepageXAtom;
  9698. codepageParam = createConstant(to->queryCharset()->queryCodepageName());
  9699. }
  9700. break;
  9701. }
  9702. case type_swapint:
  9703. {
  9704. CHqlBoundExpr recast;
  9705. ITypeInfo * type = makeIntType(from->getSize(), from->isSigned());
  9706. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9707. buildExpr(ctx, translated, recast);
  9708. assignCastUnknownLength(ctx, target, recast);
  9709. return;
  9710. }
  9711. case type_int:
  9712. case type_real:
  9713. case type_boolean:
  9714. case type_packedint:
  9715. {
  9716. Owned<ICharsetInfo> asciiCharset = getCharset(asciiAtom);
  9717. if (to->queryCharset() != asciiCharset)
  9718. {
  9719. //This should really be handled by the call processing.
  9720. CHqlBoundExpr recast;
  9721. ITypeInfo * type = makeStringType(to->getStringLen(), NULL, NULL);
  9722. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9723. buildExpr(ctx, translated, recast);
  9724. assignCastUnknownLength(ctx, target, recast);
  9725. return;
  9726. }
  9727. if (fromType == type_real)
  9728. funcName = f2axAtom;
  9729. else if (fromType == type_boolean)
  9730. funcName = bool2StrXAtom;
  9731. else if (from->isSigned())
  9732. funcName = (srclen > 4 ? ls82axAtom : ls42axAtom);
  9733. else
  9734. funcName = (srclen > 4 ? l82axAtom : l42axAtom);
  9735. args.append(*pure.getTranslatedExpr());
  9736. OwnedHqlExpr call = bindFunctionCall(funcName, args);
  9737. buildExprAssign(ctx, target, call);
  9738. return;
  9739. }
  9740. case type_void:
  9741. if (pure.expr->getOperator() != no_decimalstack)
  9742. {
  9743. throwCannotCast(from, to);
  9744. break;
  9745. }
  9746. //fall through
  9747. case type_decimal:
  9748. {
  9749. ensurePushed(ctx, pure);
  9750. OwnedHqlExpr call = bindFunctionCall(DecPopStringXAtom, args);
  9751. buildExprAssign(ctx, target, call);
  9752. return;
  9753. }
  9754. default:
  9755. assertex(!"Unknown copy source type");
  9756. return;
  9757. }
  9758. break;
  9759. }
  9760. case type_varstring:
  9761. {
  9762. unsigned srclen = from->getSize();
  9763. switch (from->getTypeCode())
  9764. {
  9765. case type_data:
  9766. case type_string:
  9767. case type_varstring:
  9768. {
  9769. ICharsetInfo * srcset = from->queryCharset();
  9770. ICharsetInfo * tgtset = to->queryCharset();
  9771. if ((srcset == tgtset) || (to->getTypeCode() == type_data) || (from->getTypeCode() == type_data))
  9772. {
  9773. funcName = str2VStrXAtom;
  9774. }
  9775. else
  9776. {
  9777. funcName = estr2VStrXAtom;
  9778. }
  9779. }
  9780. break;
  9781. case type_unicode:
  9782. {
  9783. funcName = unicode2VCodepageXAtom;
  9784. codepageParam = createConstant(to->queryCharset()->queryCodepageName());
  9785. }
  9786. break;
  9787. case type_varunicode:
  9788. {
  9789. funcName = vunicode2VCodepageXAtom;
  9790. codepageParam = createConstant(to->queryCharset()->queryCodepageName());
  9791. }
  9792. break;
  9793. case type_qstring:
  9794. case type_utf8:
  9795. {
  9796. CHqlBoundExpr recast;
  9797. ITypeInfo * type = makeStringType(from->getStringLen(), NULL, NULL);
  9798. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9799. buildExpr(ctx, translated, recast);
  9800. assignCastUnknownLength(ctx, target, recast);
  9801. return;
  9802. }
  9803. case type_swapint:
  9804. {
  9805. CHqlBoundExpr recast;
  9806. ITypeInfo * type = makeIntType(from->getSize(), from->isSigned());
  9807. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9808. buildExpr(ctx, translated, recast);
  9809. assignCastUnknownLength(ctx, target, recast);
  9810. return;
  9811. }
  9812. case type_int:
  9813. case type_packedint:
  9814. {
  9815. //l2an4(tgtlen, tgt, expr);
  9816. if (from->isSigned())
  9817. funcName = (srclen > 4 ? ls82vxAtom : ls42vxAtom);
  9818. else
  9819. funcName = (srclen > 4 ? l82vxAtom : l42vxAtom);
  9820. break;
  9821. }
  9822. case type_boolean:
  9823. {
  9824. funcName = bool2VStrXAtom;
  9825. break;
  9826. }
  9827. case type_real:
  9828. {
  9829. funcName = f2vxAtom;;
  9830. break;
  9831. }
  9832. case type_void:
  9833. if (pure.expr->getOperator() != no_decimalstack)
  9834. {
  9835. throwCannotCast(from, to);
  9836. break;
  9837. }
  9838. //fall through
  9839. case type_decimal:
  9840. {
  9841. ensurePushed(ctx, pure);
  9842. OwnedHqlExpr call = bindFunctionCall(DecPopVStringXAtom, args);
  9843. buildExprAssign(ctx, target, call);
  9844. return;
  9845. }
  9846. default:
  9847. assertex(!"Unknown copy source type");
  9848. return;
  9849. }
  9850. break;
  9851. }
  9852. case type_unicode:
  9853. {
  9854. switch (fromType)
  9855. {
  9856. case type_unicode:
  9857. funcName = unicode2UnicodeXAtom;
  9858. break;
  9859. case type_varunicode:
  9860. funcName = vunicode2UnicodeXAtom;
  9861. break;
  9862. case type_utf8:
  9863. funcName = utf82UnicodeXAtom;
  9864. break;
  9865. case type_data:
  9866. funcName = codepage2UnicodeXAtom;
  9867. codepageParam = createConstant(from->queryCharset()->queryCodepageName());
  9868. pure.expr.setown(createValue(no_implicitcast, makeStringType(from->getStringLen(), NULL, NULL), LINK(pure.expr)));
  9869. break;
  9870. case type_string:
  9871. funcName = codepage2UnicodeXAtom;
  9872. codepageParam = createConstant(from->queryCharset()->queryCodepageName());
  9873. pure.expr.setown(createValue(no_typetransfer, makeStringType(from->getStringLen(), NULL, NULL), LINK(pure.expr)));
  9874. break;
  9875. case type_varstring:
  9876. funcName = vcodepage2UnicodeXAtom;
  9877. codepageParam = createConstant(from->queryCharset()->queryCodepageName());
  9878. pure.expr.setown(createValue(no_typetransfer, makeVarStringType(from->getStringLen(), NULL, NULL), LINK(pure.expr)));
  9879. break;
  9880. default:
  9881. CHqlBoundExpr recast;
  9882. ITypeInfo * type = makeStringType(to->getStringLen(), NULL, NULL);
  9883. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9884. buildExpr(ctx, translated, recast);
  9885. assignCastUnknownLength(ctx, target, recast);
  9886. return;
  9887. }
  9888. break;
  9889. }
  9890. case type_varunicode:
  9891. {
  9892. switch (fromType)
  9893. {
  9894. case type_unicode:
  9895. case type_utf8: // go via unicode
  9896. funcName = unicode2VUnicodeXAtom;
  9897. break;
  9898. case type_varunicode:
  9899. funcName = vunicode2VUnicodeXAtom;
  9900. break;
  9901. case type_string:
  9902. case type_data:
  9903. funcName = codepage2VUnicodeXAtom;
  9904. codepageParam = createConstant(from->queryCharset()->queryCodepageName());
  9905. pure.expr.setown(createValue(no_typetransfer, makeStringType(from->getStringLen(), NULL, NULL), LINK(pure.expr)));
  9906. break;
  9907. case type_varstring:
  9908. funcName = vcodepage2VUnicodeXAtom;
  9909. codepageParam = createConstant(from->queryCharset()->queryCodepageName());
  9910. pure.expr.setown(createValue(no_typetransfer, makeVarStringType(from->getStringLen(), NULL, NULL), LINK(pure.expr)));
  9911. break;
  9912. default:
  9913. CHqlBoundExpr recast;
  9914. ITypeInfo * type = makeStringType(to->getStringLen(), NULL, NULL);
  9915. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9916. buildExpr(ctx, translated, recast);
  9917. assignCastUnknownLength(ctx, target, recast);
  9918. return;
  9919. }
  9920. break;
  9921. }
  9922. case type_utf8:
  9923. {
  9924. switch (fromType)
  9925. {
  9926. case type_unicode:
  9927. case type_varunicode:
  9928. funcName = unicodeToUtf8XAtom;
  9929. break;
  9930. case type_utf8:
  9931. funcName = utf8ToUtf8XAtom;
  9932. break;
  9933. case type_string:
  9934. case type_data:
  9935. case type_varstring:
  9936. funcName = codepageToUtf8XAtom;
  9937. codepageParam = createConstant(from->queryCharset()->queryCodepageName());
  9938. pure.expr.setown(createValue(no_typetransfer, makeStringType(from->getStringLen(), NULL, NULL), LINK(pure.expr)));
  9939. break;
  9940. default:
  9941. CHqlBoundExpr recast;
  9942. ITypeInfo * type = makeStringType(to->getStringLen(), NULL, NULL);
  9943. OwnedHqlExpr translated = createValue(no_implicitcast, type, pure.getTranslatedExpr());
  9944. buildExpr(ctx, translated, recast);
  9945. assignCastUnknownLength(ctx, target, recast);
  9946. return;
  9947. }
  9948. break;
  9949. }
  9950. case type_set:
  9951. if (isSameBasicType(to->queryChildType(), from->queryChildType()))
  9952. {
  9953. if (!target.isAll)
  9954. {
  9955. //Ugly. Create a dummy isAll field to assign to..
  9956. assertex(!pure.isAll || matchesBoolean(pure.isAll, false));
  9957. CHqlBoundTarget tempTarget;
  9958. tempTarget.set(target);
  9959. tempTarget.isAll.setown(ctx.getTempDeclare(queryBoolType(), NULL));
  9960. assignCastUnknownLength(ctx, tempTarget, pure);
  9961. return;
  9962. }
  9963. funcName = set2SetXAtom;
  9964. }
  9965. else
  9966. {
  9967. OwnedHqlExpr values = pure.getTranslatedExpr();
  9968. buildSetAssignViaBuilder(ctx, target, values);
  9969. return;
  9970. }
  9971. break;
  9972. case type_table:
  9973. case type_groupedtable:
  9974. {
  9975. OwnedHqlExpr src = pure.getTranslatedExpr();
  9976. buildDatasetAssign(ctx, target, src);
  9977. return;
  9978. }
  9979. default:
  9980. assertex(!"Unexpected target type for variable length");
  9981. break;
  9982. }
  9983. args.append(*pure.getTranslatedExpr());
  9984. if(codepageParam)
  9985. args.append(*codepageParam);
  9986. OwnedHqlExpr call = bindFunctionCall(funcName, args);
  9987. buildExprAssign(ctx, target, call);
  9988. }
  9989. void HqlCppTranslator::expandFunctions(bool expandInline)
  9990. {
  9991. if (expandInline)
  9992. {
  9993. BuildCtx ctx(*code, prototypeAtom);
  9994. ForEachItemIn(idx, code->helpers)
  9995. {
  9996. IHqlExpression & cur = (IHqlExpression &)code->helpers.item(idx);
  9997. StringBuffer init;
  9998. if (getProperty(cur.queryChild(0), initfunctionAtom, init))
  9999. {
  10000. StringBuffer initproto("extern \"C\" void SERVICE_API ");
  10001. initproto.append(init).append("(const char *);");
  10002. ctx.addQuoted(initproto);
  10003. }
  10004. expandFunctionPrototype(ctx, &cur);
  10005. }
  10006. }
  10007. else
  10008. {
  10009. CIArray includes;
  10010. BuildCtx ctx(*code, includeAtom);
  10011. ForEachItemIn(idx, code->helpers)
  10012. {
  10013. //StringBuffer include;
  10014. //IHqlExpression & cur = (IHqlExpression &)code->helpers.item(idx);
  10015. // getLibraryName(cur, include);
  10016. //MORE!! Get the include name...
  10017. }
  10018. }
  10019. }
  10020. void HqlCppTranslator::bindAndPush(BuildCtx & ctx, IHqlExpression * value)
  10021. {
  10022. CHqlBoundExpr bound;
  10023. buildExpr(ctx, value, bound);
  10024. ensurePushed(ctx, bound);
  10025. }
  10026. bool HqlCppTranslator::ensurePushed(BuildCtx & ctx, const CHqlBoundExpr & pure)
  10027. {
  10028. if (!isPushed(pure))
  10029. {
  10030. //Temporary solution - create a critical block whenever the decimals are used.
  10031. OwnedHqlExpr marker = createAttribute(decimalAtom);
  10032. if (!ctx.queryMatchExpr(marker))
  10033. {
  10034. //If a group with no {} is added, we might get a name clash => make it unique
  10035. StringBuffer s;
  10036. getUniqueId(s.append("BcdCriticalBlock bcd")).append(";");
  10037. ctx.addQuoted(s);
  10038. ctx.associateExpr(marker, NULL);
  10039. }
  10040. ITypeInfo * type = pure.expr->queryType();
  10041. HqlExprArray args;
  10042. _ATOM funcName = NULL;
  10043. switch (type->getTypeCode())
  10044. {
  10045. case type_data:
  10046. case type_string:
  10047. case type_varstring:
  10048. funcName = DecPushStringAtom;
  10049. if (type->queryCharset()->queryName() == ebcdicAtom)
  10050. {
  10051. CHqlBoundExpr temp;
  10052. OwnedHqlExpr translated = pure.getTranslatedExpr();
  10053. OwnedHqlExpr cast = createValue(no_cast, getAsciiType(type), translated.getClear());
  10054. buildExpr(ctx, cast, temp);
  10055. args.append(*getBoundLength(temp));
  10056. args.append(*getElementPointer(temp.expr));
  10057. }
  10058. else
  10059. {
  10060. args.append(*getBoundLength(pure));
  10061. args.append(*getElementPointer(pure.expr));
  10062. }
  10063. break;
  10064. case type_qstring:
  10065. funcName = DecPushQStringAtom;
  10066. args.append(*getBoundLength(pure));
  10067. args.append(*getElementPointer(pure.expr));
  10068. break;
  10069. case type_unicode:
  10070. case type_varunicode:
  10071. funcName = DecPushUnicodeAtom;
  10072. args.append(*getBoundLength(pure));
  10073. args.append(*getElementPointer(pure.expr));
  10074. break;
  10075. case type_utf8:
  10076. funcName = DecPushUtf8Atom;
  10077. args.append(*getBoundLength(pure));
  10078. args.append(*getElementPointer(pure.expr));
  10079. break;
  10080. case type_decimal:
  10081. funcName = type->isSigned() ? DecPushDecimalAtom : DecPushUDecimalAtom;
  10082. args.append(*getPointer(pure.expr));
  10083. args.append(*getSizetConstant(type->getSize()));
  10084. args.append(*getSizetConstant(type->getPrecision()));
  10085. break;
  10086. case type_swapint:
  10087. {
  10088. CHqlBoundExpr copyPure;
  10089. copyPure.set(pure);
  10090. //cast via intermediate int.
  10091. OwnedITypeInfo tempType = makeIntType(type->getSize(), type->isSigned());
  10092. CHqlBoundExpr boundCast;
  10093. doBuildExprCast(ctx, tempType, copyPure, boundCast);
  10094. funcName = type->isSigned() ? DecPushInt64Atom : DecPushUInt64Atom;
  10095. args.append(*boundCast.expr.getLink());
  10096. break;
  10097. }
  10098. //fall through
  10099. case type_int:
  10100. case type_packedint:
  10101. //more signed/unsigned and optimize the length...
  10102. funcName = type->isSigned() ? DecPushInt64Atom : DecPushUInt64Atom;
  10103. args.append(*pure.expr.getLink());
  10104. break;
  10105. case type_enumerated:
  10106. throwError2(HQLERR_CastXNotImplemented, "map", "decimal");
  10107. break;
  10108. case type_boolean:
  10109. funcName = DecPushLongAtom;
  10110. args.append(*pure.expr.getLink());
  10111. break;
  10112. case type_real:
  10113. funcName = DecPushRealAtom;
  10114. args.append(*pure.expr.getLink());
  10115. break;
  10116. default:
  10117. throwError2(HQLERR_CastXNotImplemented, "unknown", "varstring");
  10118. break;
  10119. }
  10120. if (funcName)
  10121. callProcedure(ctx, funcName, args);
  10122. return true;
  10123. }
  10124. return false;
  10125. }
  10126. static StringBuffer & appendCapital(StringBuffer & s, StringBuffer & _name)
  10127. {
  10128. const char * name = _name.str();
  10129. if (name && name[0])
  10130. {
  10131. s.append((char)toupper(*name));
  10132. s.append(name+1);
  10133. }
  10134. return s;
  10135. }
  10136. bool HqlCppTranslator::expandFunctionPrototype(StringBuffer & s, IHqlExpression * funcdef)
  10137. {
  10138. return generateFunctionPrototype(s, funcdef, options.targetCompiler);
  10139. }
  10140. void HqlCppTranslator::expandFunctionPrototype(BuildCtx & ctx, IHqlExpression * funcdef)
  10141. {
  10142. StringBuffer s;
  10143. if (expandFunctionPrototype(s, funcdef))
  10144. {
  10145. s.append(";");
  10146. ctx.addQuoted(s);
  10147. }
  10148. }
  10149. //Replace no_param with whatever they will have been bound to
  10150. static IHqlExpression * replaceInlineParameters(IHqlExpression * funcdef, IHqlExpression * expr)
  10151. {
  10152. IHqlExpression * body = funcdef->queryChild(0);
  10153. assertex(!body->hasProperty(oldSetFormatAtom));
  10154. IHqlExpression * formals = funcdef->queryChild(1);
  10155. HqlMapTransformer simpleTransformer;
  10156. StringBuffer paramNameText, temp;
  10157. ForEachChild(i, formals)
  10158. {
  10159. IHqlExpression * param = formals->queryChild(i);
  10160. ITypeInfo *paramType = param->queryType();
  10161. CHqlBoundExpr bound;
  10162. //Case is significant if these parameters are use for BEGINC++ sections
  10163. _ATOM paramName = param->queryName();
  10164. paramNameText.clear().append(paramName).toLowerCase();
  10165. Linked<ITypeInfo> type = paramType;
  10166. switch (paramType->getTypeCode())
  10167. {
  10168. case type_set:
  10169. {
  10170. appendCapital(temp.clear().append("isAll"), paramNameText);
  10171. bound.isAll.setown(createVariable(temp.str(), makeBoolType()));
  10172. }
  10173. //fall through
  10174. case type_string:
  10175. case type_qstring:
  10176. case type_data:
  10177. case type_unicode:
  10178. case type_utf8:
  10179. case type_table:
  10180. case type_groupedtable:
  10181. if (paramType->getSize() == UNKNOWN_LENGTH)
  10182. {
  10183. appendCapital(temp.clear().append("len"), paramNameText);
  10184. bound.length.setown(createVariable(temp.str(), LINK(sizetType)));
  10185. }
  10186. type.setown(makeReferenceModifier(LINK(type)));
  10187. break;
  10188. }
  10189. bound.expr.setown(createVariable(paramNameText.str(), LINK(type)));
  10190. OwnedHqlExpr replacement = bound.getTranslatedExpr();
  10191. simpleTransformer.setMapping(param, replacement);
  10192. }
  10193. return simpleTransformer.transformRoot(expr);
  10194. }
  10195. void HqlCppTranslator::doBuildUserFunctionReturn(BuildCtx & ctx, ITypeInfo * type, IHqlExpression * value)
  10196. {
  10197. if (!options.spotCSE)
  10198. {
  10199. doBuildFunctionReturn(ctx, type, value);
  10200. return;
  10201. }
  10202. switch (value->getOperator())
  10203. {
  10204. case no_if:
  10205. if (false)///disable for the moment - look at changes in klogermann11 to see why, some v.good, some bad.
  10206. {
  10207. //optimize the way that cses are spotted to minimise unnecessary calculations
  10208. OwnedHqlExpr branches = createComma(LINK(value->queryChild(1)), LINK(value->queryChild(2)));
  10209. OwnedHqlExpr cond = LINK(value->queryChild(0));
  10210. spotScalarCSE(cond, branches, NULL, NULL);
  10211. BuildCtx subctx(ctx);
  10212. IHqlStmt * stmt = buildFilterViaExpr(subctx, cond);
  10213. doBuildUserFunctionReturn(subctx, type, branches->queryChild(0));
  10214. subctx.selectElse(stmt);
  10215. doBuildUserFunctionReturn(subctx, type, branches->queryChild(1));
  10216. break;
  10217. }
  10218. default:
  10219. {
  10220. OwnedHqlExpr optimized = spotScalarCSE(value);
  10221. if (value->isAction())
  10222. buildStmt(ctx, value);
  10223. else
  10224. doBuildFunctionReturn(ctx, type, optimized);
  10225. break;
  10226. }
  10227. }
  10228. }
  10229. void HqlCppTranslator::buildFunctionDefinition(IHqlExpression * funcdef)
  10230. {
  10231. IHqlExpression * outofline = funcdef->queryChild(0);
  10232. ITypeInfo * returnType = funcdef->queryType()->queryChildType();
  10233. assertex(outofline->getOperator() == no_outofline);
  10234. IHqlExpression * bodyCode = outofline->queryChild(0);
  10235. StringBuffer s;
  10236. BuildCtx funcctx(*code, helperAtom);
  10237. if (options.spanMultipleCpp)
  10238. {
  10239. const bool inChildActivity = true; // assume the worse
  10240. OwnedHqlExpr pass = getSizetConstant(cppIndexNextActivity(inChildActivity));
  10241. funcctx.addGroupPass(pass);
  10242. }
  10243. expandFunctionPrototype(s, funcdef);
  10244. if (bodyCode->getOperator() == no_cppbody)
  10245. {
  10246. if (!allowEmbeddedCpp())
  10247. throwError(HQLERR_EmbeddedCppNotAllowed);
  10248. processCppBodyDirectives(bodyCode);
  10249. IHqlExpression * location = queryLocation(bodyCode);
  10250. const char * locationFilename = location ? location->querySourcePath()->str() : NULL;
  10251. unsigned startLine = location ? location->getStartLine() : 0;
  10252. IHqlExpression * cppBody = bodyCode->queryChild(0);
  10253. if (cppBody->getOperator() == no_record)
  10254. cppBody = bodyCode->queryChild(1);
  10255. StringBuffer text;
  10256. cppBody->queryValue()->getStringValue(text);
  10257. //remove #option, and remove /r so we don't end up with mixed format end of lines.
  10258. text.setLength(cleanupEmbeddedCpp(text.length(), (char*)text.str()));
  10259. const char * start = text.str();
  10260. loop
  10261. {
  10262. char next = *start;
  10263. if (next == '\n')
  10264. startLine++;
  10265. else if (next != '\r')
  10266. break;
  10267. start++;
  10268. }
  10269. const char * body = start;
  10270. const char * cppSeparatorText = "#body";
  10271. const char * separator = strstr(body, cppSeparatorText);
  10272. if (separator)
  10273. {
  10274. text.setCharAt(separator-text.str(), 0);
  10275. if (location)
  10276. funcctx.addLine(locationFilename, startLine);
  10277. funcctx.addQuoted(body);
  10278. if (location)
  10279. funcctx.addLine();
  10280. body = separator + strlen(cppSeparatorText);
  10281. if (*body == '\r') body++;
  10282. if (*body == '\n') body++;
  10283. startLine += memcount(body-start, start, '\n');
  10284. }
  10285. funcctx.addQuotedCompound(s);
  10286. if (location)
  10287. funcctx.addLine(locationFilename, startLine);
  10288. funcctx.addQuoted(body);
  10289. if (location)
  10290. funcctx.addLine();
  10291. }
  10292. else
  10293. {
  10294. funcctx.addQuotedCompound(s);
  10295. //MORE: Need to work out how to handle functions that require the context.
  10296. //Need to create a class instead.
  10297. assertex(!outofline->hasProperty(contextAtom));
  10298. OwnedHqlExpr newCode = replaceInlineParameters(funcdef, bodyCode);
  10299. newCode.setown(foldHqlExpression(newCode));
  10300. doBuildUserFunctionReturn(funcctx, returnType, newCode);
  10301. }
  10302. }
  10303. //---------------------------------------------------------------------------
  10304. void HqlCppTranslator::doBuildPureSubExpr(BuildCtx & ctx, IHqlExpression * expr, CHqlBoundExpr & tgt)
  10305. {
  10306. unsigned max = expr->numChildren();
  10307. if (max == 0)
  10308. tgt.expr.set(expr);
  10309. else
  10310. {
  10311. HqlExprArray args;
  10312. unsigned idx = 0;
  10313. CHqlBoundExpr bound;
  10314. for (idx = 0; idx < max; idx++)
  10315. {
  10316. buildExpr(ctx, expr->queryChild(idx), bound);
  10317. args.append(*bound.expr.getClear());
  10318. }
  10319. tgt.expr.setown(expr->clone(args));
  10320. }
  10321. }
  10322. //---------------------------------------------------------------------------
  10323. IHqlExpression * HqlCppTranslator::getListLength(BuildCtx & ctx, IHqlExpression * expr)
  10324. {
  10325. CHqlBoundExpr bound;
  10326. buildExpr(ctx, expr, bound);
  10327. return getBoundLength(bound);
  10328. }
  10329. IHqlExpression * HqlCppTranslator::getBoundCount(const CHqlBoundExpr & bound)
  10330. {
  10331. if (bound.count)
  10332. return bound.count.getLink();
  10333. ITypeInfo * type = bound.expr->queryType();
  10334. switch (type->getTypeCode())
  10335. {
  10336. case type_array:
  10337. {
  10338. if (bound.length)
  10339. return convertBetweenCountAndSize(bound, true);
  10340. unsigned size = type->getSize();
  10341. if (size != UNKNOWN_LENGTH)
  10342. return getSizetConstant(size / type->queryChildType()->getSize());
  10343. UNIMPLEMENTED;
  10344. }
  10345. case type_table:
  10346. case type_groupedtable:
  10347. case type_set:
  10348. if (bound.length)
  10349. return convertBetweenCountAndSize(bound, true);
  10350. UNIMPLEMENTED;
  10351. default:
  10352. UNIMPLEMENTED;
  10353. }
  10354. }
  10355. IHqlExpression * HqlCppTranslator::getBoundLength(const CHqlBoundExpr & bound)
  10356. {
  10357. if (bound.length)
  10358. return bound.length.getLink();
  10359. ITypeInfo * type = bound.expr->queryType();
  10360. if (bound.expr->queryValue())
  10361. return getSizetConstant(type->getStringLen());
  10362. switch (type->getTypeCode())
  10363. {
  10364. case type_varstring:
  10365. {
  10366. HqlExprArray args;
  10367. args.append(*getElementPointer(bound.expr));
  10368. return bindTranslatedFunctionCall(strlenAtom, args);
  10369. }
  10370. case type_varunicode:
  10371. {
  10372. HqlExprArray args;
  10373. args.append(*getElementPointer(bound.expr));
  10374. return bindTranslatedFunctionCall(unicodeStrlenAtom, args);
  10375. }
  10376. case type_set:
  10377. case type_array:
  10378. case type_table:
  10379. case type_groupedtable:
  10380. assertex(!isArrayRowset(type));
  10381. if (bound.count)
  10382. return convertBetweenCountAndSize(bound, false);
  10383. UNIMPLEMENTED;
  10384. case type_utf8:
  10385. {
  10386. assertex(type->getSize() != UNKNOWN_LENGTH);
  10387. HqlExprArray args;
  10388. args.append(*getSizetConstant(type->getSize()));
  10389. args.append(*getElementPointer(bound.expr));
  10390. return bindTranslatedFunctionCall(utf8LengthAtom, args);
  10391. }
  10392. default:
  10393. return getSizetConstant(type->getStringLen());
  10394. }
  10395. }
  10396. IHqlExpression * HqlCppTranslator::getBoundSize(ITypeInfo * type, IHqlExpression * length, IHqlExpression * data)
  10397. {
  10398. type_t tc = type->getTypeCode();
  10399. ITypeInfo * lengthType = length->queryType();
  10400. switch (tc)
  10401. {
  10402. case type_qstring:
  10403. {
  10404. if (length->queryValue())
  10405. return getSizetConstant((size32_t)rtlQStrSize((size32_t)length->queryValue()->getIntValue()));
  10406. HqlExprArray args;
  10407. args.append(*LINK(length));
  10408. return bindTranslatedFunctionCall(qstrSizeAtom, args);
  10409. }
  10410. case type_varstring:
  10411. return adjustValue(length, 1);
  10412. case type_varunicode:
  10413. {
  10414. OwnedHqlExpr temp = adjustValue(length, 1);
  10415. return multiplyValue(temp, 2);
  10416. }
  10417. case type_unicode:
  10418. return multiplyValue(length, 2);
  10419. case type_utf8:
  10420. {
  10421. assertex(data);
  10422. if (data->queryValue())
  10423. return getSizetConstant(data->queryValue()->getSize());
  10424. HqlExprArray args;
  10425. args.append(*LINK(length));
  10426. args.append(*getElementPointer(data));
  10427. return bindTranslatedFunctionCall(utf8SizeAtom, args);
  10428. }
  10429. case type_array:
  10430. case type_set:
  10431. return LINK(length);
  10432. default:
  10433. return LINK(length);
  10434. }
  10435. }
  10436. IHqlExpression * HqlCppTranslator::getBoundSize(const CHqlBoundExpr & bound)
  10437. {
  10438. ITypeInfo * type = bound.expr->queryType();
  10439. if (bound.length)
  10440. return getBoundSize(type, bound.length, bound.expr);
  10441. type_t tc = type->getTypeCode();
  10442. if (tc == type_row)
  10443. {
  10444. if (hasReferenceModifier(type))
  10445. return getSizetConstant(sizeof(void*));
  10446. IHqlExpression * record = ::queryRecord(type);
  10447. ColumnToOffsetMap * map = queryRecordOffsetMap(record);
  10448. if (map->isFixedWidth())
  10449. return getSizetConstant(map->getFixedRecordSize());
  10450. //call meta function mm.queryRecordSize(&row)
  10451. StringBuffer metaInstance, temp;
  10452. buildMetaForRecord(metaInstance, record);
  10453. temp.append(metaInstance).append(".getRecordSize(");
  10454. OwnedHqlExpr rowAddr = getPointer(bound.expr);
  10455. generateExprCpp(temp, rowAddr);
  10456. temp.append(")");
  10457. return createQuoted(temp.str(), LINK(sizetType));
  10458. }
  10459. if (type->getSize() != UNKNOWN_LENGTH)
  10460. return getSizetConstant(type->getSize());
  10461. OwnedHqlExpr length = getBoundLength(bound);
  10462. return getBoundSize(type, length, bound.expr);
  10463. }
  10464. IHqlExpression * HqlCppTranslator::getFirstCharacter(IHqlExpression * source)
  10465. {
  10466. if (source->getOperator() == no_constant)
  10467. {
  10468. StringBuffer temp;
  10469. source->queryValue()->getStringValue(temp);
  10470. return createUIntConstant((unsigned char)temp.charAt(0));
  10471. }
  10472. return createValue(no_index, makeCharType(), LINK(source), getZero());
  10473. }
  10474. IHqlExpression * HqlCppTranslator::getElementPointer(IHqlExpression * source)
  10475. {
  10476. ITypeInfo * srcType = source->queryType();
  10477. switch (srcType->getTypeCode())
  10478. {
  10479. case type_string:
  10480. case type_data:
  10481. case type_qstring:
  10482. case type_varstring:
  10483. case type_unicode:
  10484. case type_utf8:
  10485. case type_varunicode:
  10486. case type_set:
  10487. case type_array:
  10488. break;
  10489. default:
  10490. throwUnexpectedType(srcType);
  10491. }
  10492. if (source->getOperator() == no_constant)
  10493. return LINK(source);
  10494. OwnedHqlExpr pointer = getPointer(source);
  10495. return ensureIndexable(pointer);
  10496. }
  10497. /* All in params: NOT linked */
  10498. IHqlExpression * HqlCppTranslator::getIndexedElementPointer(IHqlExpression * source, IHqlExpression * index)
  10499. {
  10500. ITypeInfo * srcType = source->queryType();
  10501. switch (srcType->getTypeCode())
  10502. {
  10503. case type_string:
  10504. case type_data:
  10505. case type_qstring:
  10506. case type_varstring:
  10507. case type_unicode:
  10508. case type_utf8:
  10509. case type_varunicode:
  10510. break;
  10511. default:
  10512. throwUnexpectedType(srcType);
  10513. }
  10514. if (!index)
  10515. return getElementPointer(source);
  10516. IValue * value = index->queryValue();
  10517. if (value && value->getIntValue() == 0)
  10518. return getElementPointer(source);
  10519. ITypeInfo * refType = LINK(srcType);
  10520. if (!srcType->isReference())
  10521. refType = makeReferenceModifier(refType);
  10522. OwnedHqlExpr temp;
  10523. if (srcType->getTypeCode() == type_utf8)
  10524. {
  10525. HqlExprArray args;
  10526. args.append(*LINK(index));
  10527. args.append(*getElementPointer(source));
  10528. temp.setown(bindTranslatedFunctionCall(utf8SizeAtom, args));
  10529. index = temp;
  10530. }
  10531. //special case string indexing
  10532. if (source->getOperator() != no_constant)
  10533. {
  10534. if (!srcType->isReference() && !hasWrapperModifier(srcType))
  10535. return createValue(no_address, refType, createValue(no_index, makeCharType(), ensureIndexable(source), LINK(index)));
  10536. }
  10537. return createValue(no_add, refType, ensureIndexable(source), LINK(index));
  10538. }
  10539. IHqlExpression * HqlCppTranslator::getIndexedElementPointer(IHqlExpression * source, unsigned index)
  10540. {
  10541. if (!index)
  10542. return getElementPointer(source);
  10543. OwnedHqlExpr ival = getSizetConstant(index);
  10544. return getIndexedElementPointer(source, ival);
  10545. }
  10546. IHqlExpression * HqlCppTranslator::needFunction(_ATOM name)
  10547. {
  10548. HqlDummyLookupContext dummyctx(errors);
  10549. return internalScope->lookupSymbol(name, LSFsharedOK, dummyctx);
  10550. }
  10551. unsigned HqlCppTranslator::processHint(IHqlExpression * expr)
  10552. {
  10553. unsigned oldHints = hints;
  10554. _ATOM hint = NULL; // MORE how do I get this?
  10555. if (hint == sizeAtom)
  10556. hints = (hints & ~(HintSpeed|HintSize)) | HintSize;
  10557. else if (hint == speedAtom)
  10558. hints = (hints & ~(HintSize|HintSpeed)) | HintSpeed;
  10559. return oldHints;
  10560. }
  10561. bool HqlCppTranslator::childrenRequireTemp(BuildCtx & ctx, IHqlExpression * expr, bool includeChildren)
  10562. {
  10563. unsigned numArgs = expr->numChildren();
  10564. for (unsigned index = 0; index < numArgs; index++)
  10565. if (requiresTemp(ctx, expr->queryChild(index), includeChildren))
  10566. return true;
  10567. return false;
  10568. }
  10569. bool HqlCppTranslator::requiresTemp(BuildCtx & ctx, IHqlExpression * expr, bool includeChildren)
  10570. {
  10571. switch (expr->getOperator())
  10572. {
  10573. case no_attr:
  10574. case no_attr_link:
  10575. case no_attr_expr:
  10576. case no_quoted:
  10577. case no_variable:
  10578. case no_constant:
  10579. case no_translated:
  10580. case no_matchtext:
  10581. case no_matchunicode:
  10582. case no_matchlength:
  10583. case no_matchattr:
  10584. case no_matchrow:
  10585. case no_matchutf8:
  10586. case no_libraryinput:
  10587. return false;
  10588. case no_getresult:
  10589. case no_getgraphresult:
  10590. case no_workunit_dataset:
  10591. return false; // if in an activity, then will be in setContext, if not then don't really care
  10592. case no_preservemeta:
  10593. return requiresTemp(ctx, expr->queryChild(0), includeChildren);
  10594. case no_alias:
  10595. {
  10596. if (expr->isPure() && ctx.queryMatchExpr(expr->queryChild(0)))
  10597. return false;
  10598. if (!containsActiveDataset(expr)) // generates a earlier temp even if generating within the onCreate() function
  10599. return false;
  10600. return true;
  10601. }
  10602. case no_select:
  10603. if (expr->hasProperty(newAtom))
  10604. {
  10605. IHqlExpression * ds= expr->queryChild(0);
  10606. if (!ds->isPure() || !ds->isDatarow())
  10607. return true;
  10608. if (!ctx.queryAssociation(ds, AssocRow, NULL))
  10609. return true;
  10610. }
  10611. return false;
  10612. case no_field:
  10613. throwUnexpected();
  10614. return false; // more, depends on whether conditional etc.
  10615. case no_sizeof:
  10616. case no_offsetof:
  10617. return false; /// auto creates one anyway.
  10618. case no_typetransfer:
  10619. switch (expr->queryChild(0)->queryType()->getTypeCode())
  10620. {
  10621. case type_qstring:
  10622. case type_string:
  10623. case type_data:
  10624. case type_varstring:
  10625. break;
  10626. default:
  10627. return true;
  10628. }
  10629. break;
  10630. case no_substring:
  10631. {
  10632. SubStringInfo info(expr);
  10633. if (!info.canGenerateInline() && !expr->hasProperty(quickAtom))
  10634. return true;
  10635. break;
  10636. }
  10637. case no_call:
  10638. case no_externalcall:
  10639. {
  10640. ITypeInfo * type = expr->queryType();
  10641. switch (type->getTypeCode())
  10642. {
  10643. case type_string:
  10644. case type_data:
  10645. case type_qstring:
  10646. case type_varstring:
  10647. case type_unicode:
  10648. case type_varunicode:
  10649. case type_utf8:
  10650. return true;
  10651. }
  10652. break;
  10653. }
  10654. case no_cast:
  10655. case no_implicitcast:
  10656. {
  10657. ITypeInfo * type = expr->queryType();
  10658. IHqlExpression * child = expr->queryChild(0);
  10659. switch (type->getTypeCode())
  10660. {
  10661. case type_string:
  10662. case type_data:
  10663. if (!canRemoveStringCast(type, child->queryType()))
  10664. return true;
  10665. break;
  10666. case type_varstring:
  10667. if ((type->getSize() != UNKNOWN_LENGTH) || (child->queryType()->getTypeCode() != type_varstring))
  10668. return true;
  10669. break;
  10670. }
  10671. }
  10672. break;
  10673. case no_eq:
  10674. case no_ne:
  10675. case no_lt:
  10676. case no_le:
  10677. case no_gt:
  10678. case no_ge:
  10679. {
  10680. if (!includeChildren)
  10681. return false;
  10682. unsigned numArgs = expr->numChildren();
  10683. for (unsigned index = 0; index < numArgs; index++)
  10684. {
  10685. OwnedHqlExpr cur = getSimplifyCompareArg(expr->queryChild(index));
  10686. //decimal comparisons can't be short circuited because they might cause a bcd stack overflow.
  10687. if (cur->queryType()->getTypeCode() == type_decimal)
  10688. return true;
  10689. if (requiresTemp(ctx, cur, true))
  10690. return true;
  10691. }
  10692. return false;
  10693. }
  10694. case no_mul:
  10695. case no_div:
  10696. case no_modulus:
  10697. case no_add:
  10698. case no_sub:
  10699. case no_and:
  10700. case no_or:
  10701. case no_xor:
  10702. case no_lshift:
  10703. case no_rshift:
  10704. case no_comma:
  10705. case no_compound:
  10706. case no_band:
  10707. case no_bor:
  10708. case no_bxor:
  10709. case no_pselect:
  10710. case no_index:
  10711. case no_postinc:
  10712. case no_postdec:
  10713. case no_negate:
  10714. case no_not:
  10715. case no_bnot:
  10716. case no_address:
  10717. case no_deref:
  10718. case no_preinc:
  10719. case no_predec:
  10720. case no_if:
  10721. case no_charlen:
  10722. break;
  10723. case no_between:
  10724. //Assume the worse for decimals.
  10725. if (expr->queryChild(0)->queryType()->getTypeCode() == type_decimal)
  10726. return true;
  10727. break;
  10728. case no_order:
  10729. case no_crc:
  10730. case no_hash:
  10731. case no_hash32:
  10732. case no_hash64:
  10733. case no_hashmd5:
  10734. case no_abs:
  10735. return true;
  10736. default:
  10737. return true;
  10738. }
  10739. if (includeChildren)
  10740. return childrenRequireTemp(ctx, expr, includeChildren);
  10741. return false;
  10742. }
  10743. bool HqlCppTranslator::requiresTempAfterFirst(BuildCtx & ctx, IHqlExpression * expr)
  10744. {
  10745. unsigned numArgs = expr->numChildren();
  10746. for (unsigned index = 1; index < numArgs; index++)
  10747. if (requiresTemp(ctx, expr->queryChild(index), true))
  10748. return true;
  10749. return false;
  10750. }
  10751. void HqlCppTranslator::useFunction(IHqlExpression * func)
  10752. {
  10753. code->useFunction(func);
  10754. }
  10755. void HqlCppTranslator::useLibrary(const char * libname)
  10756. {
  10757. code->useLibrary(libname);
  10758. }
  10759. //===========================================================================
  10760. static unique_id_t queryInstance = 0;
  10761. HqlQueryInstance::HqlQueryInstance()
  10762. {
  10763. instance = ++queryInstance;
  10764. }
  10765. StringBuffer & HqlQueryInstance::queryDllName(StringBuffer & out)
  10766. {
  10767. return out.append("query").append(instance);
  10768. }