pasresolver.pp 470 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775
  1. {
  2. This file is part of the Free Component Library
  3. Pascal source parser
  4. Copyright (c) 2000-2005 by
  5. Areca Systems GmbH / Sebastian Guenther, [email protected]
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************
  12. Abstract:
  13. Resolves references by setting TPasElement.CustomData as TResolvedReference.
  14. Creates search scopes for elements with sub identifiers by setting
  15. TPasElement.CustomData as TPasScope: unit, program, library, interface,
  16. implementation, procs
  17. Works:
  18. - built-in types as TPasUnresolvedSymbolRef: longint, int64, string, pointer, ...
  19. - references in statements, error if not found
  20. - interface and implementation types, vars, const
  21. - params, local types, vars, const
  22. - nested procedures
  23. - nested forward procs, nested must be resolved before proc body
  24. - program/library/implementation forward procs
  25. - search in used units
  26. - unitname.identifier
  27. - alias types, 'type a=b'
  28. - type alias type 'type a=type b'
  29. - choose the most compatible overloaded procedure
  30. - while..do
  31. - repeat..until
  32. - if..then..else
  33. - binary operators
  34. - case..of
  35. - try..finally..except, on, else, raise
  36. - for loop
  37. - spot duplicates
  38. - type cast base types
  39. - char
  40. - ord(), chr()
  41. - record
  42. - variants
  43. - const param makes children const too
  44. - class:
  45. - forward declaration
  46. - instance.a
  47. - find ancestor, search in ancestors
  48. - virtual, abstract, override
  49. - method body
  50. - Self
  51. - inherited
  52. - property
  53. - read var, read function
  54. - write var, write function
  55. - stored function
  56. - defaultexpr
  57. - is and as operator
  58. - nil
  59. - constructor result type, rrfNewInstance
  60. - destructor call type: rrfFreeInstance
  61. - type cast
  62. - class of
  63. - class method, property, var, const
  64. - class-of.constructor
  65. - class-of typecast upwards/downwards
  66. - class-of option to allow is-operator
  67. - typecast Self in class method upwards/downwards
  68. - property with params
  69. - default property
  70. - visibility, override: warn and fix if lower
  71. - events, proc type of object
  72. - sealed
  73. - with..do
  74. - enums - TPasEnumType, TPasEnumValue
  75. - propagate to parent scopes
  76. - function ord(): integer
  77. - function low(ordinal): ordinal
  78. - function high(ordinal): ordinal
  79. - function pred(ordinal): ordinal
  80. - function high(ordinal): ordinal
  81. - cast integer to enum
  82. - sets - TPasSetType
  83. - set of char
  84. - set of integer
  85. - set of boolean
  86. - set of enum
  87. - ranges 'a'..'z' 2..5
  88. - operators: +, -, *, ><, <=, >=
  89. - in-operator
  90. - assign operators: +=, -=, *=
  91. - include(), exclude()
  92. - typed const: check expr type
  93. - function length(const array or string): integer
  94. - procedure setlength(var array or string; newlength: integer)
  95. - ranges TPasRangeType
  96. - procedure exit, procedure exit(const function result)
  97. - check if types only refer types+const
  98. - check const expression types, e.g. bark on "const c:string=3;"
  99. - procedure inc/dec(var ordinal; decr: ordinal = 1)
  100. - function Assigned(Pointer or Class or Class-Of): boolean
  101. - arrays TPasArrayType
  102. - TPasEnumType, char, integer, range
  103. - low, high, length, setlength, assigned
  104. - function concat(array1,array2,...): array
  105. - function copy(array): array, copy(a,start), copy(a,start,end)
  106. - insert(item; var array; index: integer)
  107. - delete(var array; start, count: integer)
  108. - element
  109. - multi dimensional
  110. - const
  111. - open array, override, pass array literal, pass var
  112. - type cast array to arrays with same dimensions and compatible element type
  113. - check if var initexpr fits vartype: var a: type = expr;
  114. - built-in functions high, low for range types
  115. - procedure type
  116. - call
  117. - as function result
  118. - as parameter
  119. - Delphi without @
  120. - @@ operator
  121. - FPC equal and not equal
  122. - "is nested"
  123. - bark on arguments access mismatch
  124. - function without params: mark if call or address, rrfImplicitCallWithoutParams
  125. - procedure break, procedure continue
  126. - built-in functions pred, succ for range type and enums
  127. - untyped parameters
  128. - built-in procedure str(const boolean|integer|enumvalue|classinstance,var s: string)
  129. - pointer TPasPointerType
  130. - nil, assigned(), typecast, class, classref, dynarray, procvar
  131. - emit hints platform, deprecated, experimental, library, unimplemented
  132. - dotted unitnames
  133. - eval:
  134. - nil, true, false
  135. - range checking:
  136. - integer ranges
  137. - boolean ranges
  138. - enum ranges
  139. - char ranges
  140. - +, -, *, div, mod, /, shl, shr, or, and, xor, in, ^^, ><
  141. - =, <>, <, <=, >, >=
  142. - ord(), low(), high(), pred(), succ(), length()
  143. - string[index]
  144. - call(param)
  145. - a:=value
  146. ToDo:
  147. - range checking:
  148. - arr[index]
  149. - indexedprop[param]
  150. - case-of unique
  151. - defaultvalue
  152. - stored
  153. - fail to write a loop var inside the loop
  154. - warn: create class with abstract methods
  155. - classes - TPasClassType
  156. - nested var, const
  157. - nested types
  158. - check if constant is longint or int64
  159. - for..in..do
  160. - records - TPasRecordType,
  161. - const TRecordValues
  162. - function default(record type): record
  163. - pointer of record
  164. - proc: check if forward and impl default values match
  165. - call array of proc without ()
  166. - array+array
  167. - pointer type, ^type, @ operator, [] operator
  168. - type alias type
  169. - object
  170. - interfaces
  171. - implements, supports
  172. - TPasResString
  173. - generics, nested param lists
  174. - type helpers
  175. - record/class helpers
  176. - generics
  177. - operator overload
  178. - attributes
  179. - anonymous functions
  180. - TPasFileType
  181. - labels
  182. - many more: search for "ToDo:"
  183. Debug flags: -d<x>
  184. VerbosePasResolver
  185. Notes:
  186. Functions and function types without parameters:
  187. property P read f; // use function f, not its result
  188. f. // implicit resolve f once if param less function or function type
  189. f[] // implicit resolve f once if a param less function or function type
  190. @f; use function f, not its result
  191. @p.f; @ operator applies to f, not p
  192. @f(); @ operator applies to result of f
  193. f(); use f's result
  194. FuncVar:=Func; if mode=objfpc: incompatible
  195. if mode=delphi: implicit addr of function f
  196. if f=g then : can implicit resolve each side once
  197. p(f), f as var parameter: can implicit
  198. }
  199. unit PasResolver;
  200. {$mode objfpc}{$H+}
  201. {$inline on}
  202. {$IFOPT Q+}{$DEFINE OverflowCheckOn}{$ENDIF}
  203. {$IFOPT R+}{$DEFINE RangeCheckOn}{$ENDIF}
  204. interface
  205. uses
  206. Classes, SysUtils, Math, contnrs,
  207. PasTree, PScanner, PParser, PasResolveEval;
  208. const
  209. ParserMaxEmbeddedColumn = 2048;
  210. ParserMaxEmbeddedRow = $7fffffff div ParserMaxEmbeddedColumn;
  211. type
  212. TResolverBaseType = (
  213. btNone, // undefined
  214. btCustom, // provided by descendant resolver
  215. btContext, // a class or record
  216. btModule,
  217. btUntyped, // TPasArgument without ArgType
  218. btChar, // char
  219. btAnsiChar, // ansichar
  220. btWideChar, // widechar
  221. btString, // string
  222. btAnsiString, // ansistring
  223. btShortString, // shortstring
  224. btWideString, // widestring
  225. btUnicodeString,// unicodestring
  226. btRawByteString, // rawbytestring
  227. btSingle, // single 1.5E-45..3.4E38, digits 7-8, bytes 4
  228. btDouble, // double 5.0E-324..1.7E308, digits 15-16, bytes 8
  229. btExtended, // extended platform, double or 1.9E-4932..1.1E4932, digits 19-20, bytes 10
  230. btCExtended, // cextended
  231. btCurrency, // as int64, but least 4 digits are the decimals (*10000), bytes 8
  232. btBoolean, // boolean
  233. btByteBool, // bytebool true=not zero
  234. btWordBool, // wordbool true=not zero
  235. btLongBool, // longbool true=not zero
  236. btQWordBool, // qwordbool true=not zero
  237. btByte, // byte 0..255
  238. btShortInt, // shortint -128..127
  239. btWord, // word unsigned 2 bytes
  240. btSmallInt, // smallint signed 2 bytes
  241. btUIntSingle, // unsigned integer range of single 22bit
  242. btIntSingle, // integer range of single 23bit
  243. btLongWord, // longword unsigned 4 bytes
  244. btLongint, // longint signed 4 bytes
  245. btUIntDouble, // unsigned integer range of double 52bit
  246. btIntDouble, // integer range of double 53bit
  247. btQWord, // qword 0..18446744073709551615, bytes 8
  248. btInt64, // int64 -9223372036854775808..9223372036854775807, bytes 8
  249. btComp, // as Int64 but not ordinal
  250. btPointer, // pointer
  251. btFile, // file
  252. btText, // text
  253. btVariant, // variant
  254. btNil, // nil = pointer, class, procedure, method, ...
  255. btProc, // TPasProcedure
  256. btBuiltInProc,
  257. btSet, // [] see SubType, can also be round bracket in var a:arraytype = (x,y)
  258. btRange // a..b see SubType
  259. );
  260. TResolveBaseTypes = set of TResolverBaseType;
  261. const
  262. btAllInteger = [btByte,btShortInt,btWord,btSmallInt,btIntSingle,btUIntSingle,
  263. btLongWord,btLongint,btIntDouble,btUIntDouble,btQWord,btInt64,btComp];
  264. btAllChars = [btChar,btAnsiChar,btWideChar];
  265. btAllStrings = [btString,btAnsiString,btShortString,
  266. btWideString,btUnicodeString,btRawByteString];
  267. btAllStringAndChars = btAllStrings+btAllChars;
  268. btAllFloats = [btSingle,btDouble,btExtended,btCExtended,btCurrency];
  269. btAllBooleans = [btBoolean,btByteBool,btWordBool,btLongBool,btQWordBool];
  270. btAllRanges = btAllInteger+btAllBooleans+btAllChars;
  271. btAllStandardTypes = [
  272. btChar,
  273. btAnsiChar,
  274. btWideChar,
  275. btString,
  276. btAnsiString,
  277. btShortString,
  278. btWideString,
  279. btUnicodeString,
  280. btRawByteString,
  281. btSingle,
  282. btDouble,
  283. btExtended,
  284. btCExtended,
  285. btCurrency,
  286. btBoolean,
  287. btByteBool,
  288. btWordBool,
  289. btLongBool,
  290. btQWordBool,
  291. btByte,
  292. btShortInt,
  293. btWord,
  294. btSmallInt,
  295. btLongWord,
  296. btLongint,
  297. btQWord,
  298. btInt64,
  299. btComp,
  300. btPointer,
  301. btFile,
  302. btText,
  303. btVariant
  304. ];
  305. btArrayRangeTypes = btAllChars+[btBoolean]+btAllInteger;
  306. ResBaseTypeNames: array[TResolverBaseType] of string =(
  307. 'None',
  308. 'Custom',
  309. 'Context',
  310. 'Module',
  311. 'Untyped',
  312. 'Char',
  313. 'AnsiChar',
  314. 'WideChar',
  315. 'String',
  316. 'AnsiString',
  317. 'ShortString',
  318. 'WideString',
  319. 'UnicodeString',
  320. 'RawByteString',
  321. 'Single',
  322. 'Double',
  323. 'Extended',
  324. 'CExtended',
  325. 'Currency',
  326. 'Boolean',
  327. 'ByteBool',
  328. 'WordBool',
  329. 'LongBool',
  330. 'QWordBool',
  331. 'Byte',
  332. 'ShortInt',
  333. 'Word',
  334. 'SmallInt',
  335. 'UIntSingle',
  336. 'IntSingle',
  337. 'LongWord',
  338. 'Longint',
  339. 'UIntDouble',
  340. 'IntDouble',
  341. 'QWord',
  342. 'Int64',
  343. 'Comp',
  344. 'Pointer',
  345. 'File',
  346. 'Text',
  347. 'Variant',
  348. 'Nil',
  349. 'Procedure/Function',
  350. 'BuiltInProc',
  351. 'set',
  352. 'range..'
  353. );
  354. type
  355. TResolverBuiltInProc = (
  356. bfCustom,
  357. bfLength,
  358. bfSetLength,
  359. bfInclude,
  360. bfExclude,
  361. bfBreak,
  362. bfContinue,
  363. bfExit,
  364. bfInc,
  365. bfDec,
  366. bfAssigned,
  367. bfChr,
  368. bfOrd,
  369. bfLow,
  370. bfHigh,
  371. bfPred,
  372. bfSucc,
  373. bfStrProc,
  374. bfStrFunc,
  375. bfConcatArray,
  376. bfCopyArray,
  377. bfInsertArray,
  378. bfDeleteArray,
  379. bfTypeInfo
  380. );
  381. TResolverBuiltInProcs = set of TResolverBuiltInProc;
  382. const
  383. ResolverBuiltInProcNames: array[TResolverBuiltInProc] of string = (
  384. 'Custom',
  385. 'Length',
  386. 'SetLength',
  387. 'Include',
  388. 'Exclude',
  389. 'Break',
  390. 'Continue',
  391. 'Exit',
  392. 'Inc',
  393. 'Dec',
  394. 'Assigned',
  395. 'Chr',
  396. 'Ord',
  397. 'Low',
  398. 'High',
  399. 'Pred',
  400. 'Succ',
  401. 'Str',
  402. 'Str',
  403. 'Concat',
  404. 'Copy',
  405. 'Insert',
  406. 'Delete',
  407. 'TypeInfo'
  408. );
  409. bfAllStandardProcs = [Succ(bfCustom)..high(TResolverBuiltInProc)];
  410. const
  411. ResolverResultVar = 'Result';
  412. type
  413. { EPasResolve }
  414. EPasResolve = class(Exception)
  415. private
  416. FPasElement: TPasElement;
  417. procedure SetPasElement(AValue: TPasElement);
  418. public
  419. Id: int64;
  420. MsgType: TMessageType;
  421. MsgNumber: integer;
  422. MsgPattern: String;
  423. Args: TMessageArgs;
  424. SourcePos: TPasSourcePos;
  425. destructor Destroy; override;
  426. property PasElement: TPasElement read FPasElement write SetPasElement; // can be nil!
  427. end;
  428. type
  429. { TUnresolvedPendingRef }
  430. TUnresolvedPendingRef = class(TPasUnresolvedSymbolRef)
  431. public
  432. Element: TPasType; // TPasClassOfType or TPasPointerType
  433. end;
  434. TPasScope = class;
  435. TIterateScopeElement = procedure(El: TPasElement; ElScope, StartScope: TPasScope;
  436. Data: Pointer; var Abort: boolean) of object;
  437. { TPasScope -
  438. Elements like TPasClassType use TPasScope descendants as CustomData for
  439. their sub identifiers.
  440. TPasResolver.Scopes has a stack of TPasScope for searching identifiers.
  441. }
  442. TPasScope = Class(TResolveData)
  443. public
  444. VisibilityContext: TPasElement; // methods sets this to a TPasClassType,
  445. // used to check if the current context is allowed to access a
  446. // private/protected element
  447. class function IsStoredInElement: boolean; virtual;
  448. class function FreeOnPop: boolean; virtual;
  449. procedure IterateElements(const aName: string; StartScope: TPasScope;
  450. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  451. var Abort: boolean); virtual;
  452. procedure WriteIdentifiers(Prefix: string); virtual;
  453. end;
  454. TPasScopeClass = class of TPasScope;
  455. { TPasModuleScope }
  456. TPasModuleScope = class(TPasScope)
  457. public
  458. FirstName: string;
  459. procedure IterateElements(const aName: string; StartScope: TPasScope;
  460. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  461. var Abort: boolean); override;
  462. end;
  463. TPasIdentifierKind = (
  464. pikNone, // not yet initialized
  465. pikBaseType, // e.g. longint
  466. pikBuiltInProc, // e.g. High(), SetLength()
  467. pikSimple, // simple vars, consts, types, enums
  468. pikProc // may need parameter list with round brackets
  469. );
  470. TPasIdentifierKinds = set of TPasIdentifierKind;
  471. { TPasIdentifier }
  472. TPasIdentifier = Class(TObject)
  473. private
  474. FElement: TPasElement;
  475. procedure SetElement(AValue: TPasElement);
  476. public
  477. {$IFDEF VerbosePasResolver}
  478. Owner: TObject;
  479. {$ENDIF}
  480. Identifier: String;
  481. NextSameIdentifier: TPasIdentifier; // next identifier with same name
  482. Kind: TPasIdentifierKind;
  483. destructor Destroy; override;
  484. property Element: TPasElement read FElement write SetElement;
  485. end;
  486. { TPasIdentifierScope - elements with a list of sub identifiers }
  487. TPasIdentifierScope = Class(TPasScope)
  488. private
  489. FItems: TFPHashList;
  490. procedure InternalAdd(Item: TPasIdentifier);
  491. procedure OnClearItem(Item, Dummy: pointer);
  492. procedure OnWriteItem(Item, Dummy: pointer);
  493. public
  494. constructor Create; override;
  495. destructor Destroy; override;
  496. function FindLocalIdentifier(const Identifier: String): TPasIdentifier; inline;
  497. function FindIdentifier(const Identifier: String): TPasIdentifier; virtual;
  498. function RemoveLocalIdentifier(El: TPasElement): boolean; virtual;
  499. function AddIdentifier(const Identifier: String; El: TPasElement;
  500. const Kind: TPasIdentifierKind): TPasIdentifier; virtual;
  501. function FindElement(const aName: string): TPasElement;
  502. procedure IterateLocalElements(const aName: string; StartScope: TPasScope;
  503. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  504. var Abort: boolean);
  505. procedure IterateElements(const aName: string; StartScope: TPasScope;
  506. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  507. var Abort: boolean); override;
  508. procedure WriteIdentifiers(Prefix: string); override;
  509. end;
  510. { TPasDefaultScope - root scope }
  511. TPasDefaultScope = class(TPasIdentifierScope)
  512. public
  513. class function IsStoredInElement: boolean; override;
  514. end;
  515. { TPasSectionScope - e.g. interface, implementation, program, library }
  516. TPasSectionScope = Class(TPasIdentifierScope)
  517. public
  518. UsesScopes: TFPList; // list of TPasSectionScope
  519. constructor Create; override;
  520. destructor Destroy; override;
  521. function FindIdentifier(const Identifier: String): TPasIdentifier; override;
  522. procedure IterateElements(const aName: string; StartScope: TPasScope;
  523. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  524. var Abort: boolean); override;
  525. procedure WriteIdentifiers(Prefix: string); override;
  526. end;
  527. { TPasEnumTypeScope }
  528. TPasEnumTypeScope = Class(TPasIdentifierScope)
  529. public
  530. CanonicalSet: TPasSetType;
  531. destructor Destroy; override;
  532. end;
  533. { TPasRecordScope }
  534. TPasRecordScope = Class(TPasIdentifierScope)
  535. end;
  536. TPasClassScopeFlag = (
  537. pcsfAncestorResolved,
  538. pcsfSealed
  539. );
  540. TPasClassScopeFlags = set of TPasClassScopeFlag;
  541. { TPasClassScope }
  542. TPasClassScope = Class(TPasIdentifierScope)
  543. public
  544. AncestorScope: TPasClassScope;
  545. CanonicalClassOf: TPasClassOfType;
  546. DirectAncestor: TPasType; // TPasClassType or TPasAliasType or TPasTypeAliasType
  547. DefaultProperty: TPasProperty;
  548. Flags: TPasClassScopeFlags;
  549. destructor Destroy; override;
  550. function FindIdentifier(const Identifier: String): TPasIdentifier; override;
  551. procedure IterateElements(const aName: string; StartScope: TPasScope;
  552. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  553. var Abort: boolean); override;
  554. procedure WriteIdentifiers(Prefix: string); override;
  555. end;
  556. TPasClassScopeClass = class of TPasClassScope;
  557. { TPasProcedureScope }
  558. TPasProcedureScope = Class(TPasIdentifierScope)
  559. public
  560. DeclarationProc: TPasProcedure; // the corresponding forward declaration
  561. ImplProc: TPasProcedure; // the corresponding proc with Body
  562. OverriddenProc: TPasProcedure; // if IsOverride then this is the ancestor proc (virtual or override)
  563. ClassScope: TPasClassScope;
  564. SelfArg: TPasArgument;
  565. function FindIdentifier(const Identifier: String): TPasIdentifier; override;
  566. procedure IterateElements(const aName: string; StartScope: TPasScope;
  567. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  568. var Abort: boolean); override;
  569. function GetSelfScope: TPasProcedureScope; // get the next parent procscope with a classcope
  570. procedure WriteIdentifiers(Prefix: string); override;
  571. destructor Destroy; override;
  572. end;
  573. { TPasPropertyScope }
  574. TPasPropertyScope = Class(TPasIdentifierScope)
  575. public
  576. AncestorProp: TPasProperty; { if TPasProperty(Element).VarType=nil this is an override
  577. otherwise it is a redeclaration }
  578. destructor Destroy; override;
  579. end;
  580. { TPasExceptOnScope }
  581. TPasExceptOnScope = Class(TPasIdentifierScope)
  582. end;
  583. TPasWithScope = class;
  584. TPasWithExprScopeFlag = (
  585. wesfNeedTmpVar,
  586. wesfOnlyTypeMembers,
  587. wesfConstParent // not writable
  588. );
  589. TPasWithExprScopeFlags = set of TPasWithExprScopeFlag;
  590. { TPasWithExprScope }
  591. TPasWithExprScope = Class(TPasScope)
  592. public
  593. WithScope: TPasWithScope; // owner
  594. Index: integer;
  595. Expr: TPasExpr;
  596. Scope: TPasScope;
  597. Flags: TPasWithExprScopeFlags;
  598. class function IsStoredInElement: boolean; override;
  599. class function FreeOnPop: boolean; override;
  600. procedure IterateElements(const aName: string; StartScope: TPasScope;
  601. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  602. var Abort: boolean); override;
  603. procedure WriteIdentifiers(Prefix: string); override;
  604. end;
  605. TPasWithExprScopeClass = class of TPasWithExprScope;
  606. { TPasWithScope }
  607. TPasWithScope = Class(TPasScope)
  608. public
  609. // Element is the TPasImplWithDo
  610. ExpressionScopes: TObjectList; // list of TPasWithExprScope
  611. constructor Create; override;
  612. destructor Destroy; override;
  613. end;
  614. { TPasSubScope - base class for sub scopes aka dotted scopes }
  615. TPasSubScope = Class(TPasIdentifierScope)
  616. public
  617. class function IsStoredInElement: boolean; override;
  618. end;
  619. { TPasIterateFilterData }
  620. TPasIterateFilterData = record
  621. OnIterate: TIterateScopeElement;
  622. Data: Pointer;
  623. end;
  624. PPasIterateFilterData = ^TPasIterateFilterData;
  625. { TPasModuleDotScope - scope for searching unitname.<identifier> }
  626. TPasModuleDotScope = Class(TPasSubScope)
  627. private
  628. FModule: TPasModule;
  629. procedure OnInternalIterate(El: TPasElement; ElScope, StartScope: TPasScope;
  630. Data: Pointer; var Abort: boolean);
  631. procedure SetModule(AValue: TPasModule);
  632. public
  633. InterfaceScope: TPasSectionScope;
  634. ImplementationScope: TPasSectionScope;
  635. destructor Destroy; override;
  636. function FindIdentifier(const Identifier: String): TPasIdentifier; override;
  637. procedure IterateElements(const aName: string; StartScope: TPasScope;
  638. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  639. var Abort: boolean); override;
  640. procedure WriteIdentifiers(Prefix: string); override;
  641. property Module: TPasModule read FModule write SetModule;
  642. end;
  643. { TPasDotIdentifierScope }
  644. TPasDotIdentifierScope = Class(TPasSubScope)
  645. public
  646. IdentifierScope: TPasIdentifierScope;
  647. OnlyTypeMembers: boolean; // true=only class var/procs, false=default=all
  648. ConstParent: boolean;
  649. function FindIdentifier(const Identifier: String): TPasIdentifier; override;
  650. procedure IterateElements(const aName: string; StartScope: TPasScope;
  651. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  652. var Abort: boolean); override;
  653. procedure WriteIdentifiers(Prefix: string); override;
  654. end;
  655. { TPasDotRecordScope - used for aRecord.subidentifier }
  656. TPasDotRecordScope = Class(TPasDotIdentifierScope)
  657. end;
  658. { TPasDotEnumTypeScope - used for EnumType.EnumValue }
  659. TPasDotEnumTypeScope = Class(TPasDotIdentifierScope)
  660. end;
  661. { TPasDotClassScope - used for aClass.subidentifier }
  662. TPasDotClassScope = Class(TPasDotIdentifierScope)
  663. private
  664. FClassScope: TPasClassScope;
  665. procedure SetClassScope(AValue: TPasClassScope);
  666. public
  667. InheritedExpr: boolean; // this is 'inherited <name>' instead of '.<name'
  668. property ClassScope: TPasClassScope read FClassScope write SetClassScope;
  669. end;
  670. TResolvedReferenceFlag = (
  671. rrfDotScope, // found reference via a dot scope (TPasDotIdentifierScope)
  672. rrfImplicitCallWithoutParams, // a TPrimitiveExpr is an implicit call without params
  673. rrfNewInstance, // constructor call (without it call constructor as normal method)
  674. rrfFreeInstance, // destructor call (without it call destructor as normal method)
  675. rrfVMT, // use VMT for call
  676. rrfConstInherited // parent is const and children are too
  677. );
  678. TResolvedReferenceFlags = set of TResolvedReferenceFlag;
  679. type
  680. { TResolvedRefContext }
  681. TResolvedRefContext = Class
  682. end;
  683. TResolvedRefAccess = (
  684. rraNone,
  685. rraRead, // expression is read
  686. rraAssign, // expression is LHS assign
  687. rraReadAndAssign, // expression is LHS +=, -=, *=, /=
  688. rraVarParam, // expression is passed to a var parameter
  689. rraOutParam, // expression is passed to an out parameter
  690. rraParamToUnknownProc // used as param, before knowing what overladed proc to call,
  691. // will later be changed to rraRead, rraVarParam, rraOutParam
  692. );
  693. TPRResolveVarAccesses = set of TResolvedRefAccess;
  694. { TResolvedReference - CustomData for normal references }
  695. TResolvedReference = Class(TResolveData)
  696. private
  697. FDeclaration: TPasElement;
  698. procedure SetDeclaration(AValue: TPasElement);
  699. public
  700. Flags: TResolvedReferenceFlags;
  701. Access: TResolvedRefAccess;
  702. Context: TResolvedRefContext;
  703. WithExprScope: TPasWithExprScope;// if set, this reference used a With-block expression.
  704. destructor Destroy; override;
  705. property Declaration: TPasElement read FDeclaration write SetDeclaration;
  706. end;
  707. { TResolvedRefCtxConstructor }
  708. TResolvedRefCtxConstructor = Class(TResolvedRefContext)
  709. public
  710. Typ: TPasType; // e.g. TPasClassType
  711. end;
  712. TPasResolverResultFlag = (
  713. rrfReadable,
  714. rrfWritable,
  715. rrfAssignable, // not writable in general, e.g. aString[1]:=
  716. rrfCanBeStatement
  717. );
  718. TPasResolverResultFlags = set of TPasResolverResultFlag;
  719. type
  720. { TPasResolverResult }
  721. TPasResolverResult = record
  722. BaseType: TResolverBaseType;
  723. SubType: TResolverBaseType; // for btSet and btRange
  724. IdentEl: TPasElement; // if set then this specific identifier is the value, can be a type
  725. TypeEl: TPasType; // can be nil for const expression
  726. ExprEl: TPasExpr;
  727. Flags: TPasResolverResultFlags;
  728. end;
  729. PPasResolvedElement = ^TPasResolverResult;
  730. type
  731. TPasResolverComputeFlag = (
  732. rcSkipTypeAlias,
  733. rcSetReferenceFlags, // set flags of references while computing type, used by Resolve* methods
  734. rcNoImplicitProc, // do not call a function without params, includes rcNoImplicitProcType
  735. rcNoImplicitProcType, // do not call a proc type without params
  736. rcConstant, // resolve a constant expresson
  737. rcType // resolve a type expression
  738. );
  739. TPasResolverComputeFlags = set of TPasResolverComputeFlag;
  740. TResElDataBuiltInSymbol = Class(TResolveData)
  741. public
  742. end;
  743. { TResElDataBaseType - CustomData for compiler built-in types (TPasUnresolvedSymbolRef), e.g. longint }
  744. TResElDataBaseType = Class(TResElDataBuiltInSymbol)
  745. public
  746. BaseType: TResolverBaseType;
  747. end;
  748. TResElDataBaseTypeClass = class of TResElDataBaseType;
  749. TResElDataBuiltInProc = Class;
  750. TOnGetCallCompatibility = function(Proc: TResElDataBuiltInProc;
  751. Exp: TPasExpr; RaiseOnError: boolean): integer of object;
  752. TOnGetCallResult = procedure(Proc: TResElDataBuiltInProc; Params: TParamsExpr;
  753. out ResolvedEl: TPasResolverResult) of object;
  754. TOnEvalBIFunction = procedure(Proc: TResElDataBuiltInProc; Params: TParamsExpr;
  755. Flags: TResEvalFlags; out Evaluated: TResEvalValue) of object;
  756. TOnFinishParamsExpr = procedure(Proc: TResElDataBuiltInProc;
  757. Params: TParamsExpr) of object;
  758. TBuiltInProcFlag = (
  759. bipfCanBeStatement // a call is enough for a simple statement
  760. );
  761. TBuiltInProcFlags = set of TBuiltInProcFlag;
  762. { TResElDataBuiltInProc - TPasUnresolvedSymbolRef(aType).CustomData for compiler built-in procs like 'length' }
  763. TResElDataBuiltInProc = Class(TResElDataBuiltInSymbol)
  764. public
  765. Proc: TPasUnresolvedSymbolRef;
  766. Signature: string;
  767. BuiltIn: TResolverBuiltInProc;
  768. GetCallCompatibility: TOnGetCallCompatibility;
  769. GetCallResult: TOnGetCallResult;
  770. Eval: TOnEvalBIFunction;
  771. FinishParamsExpression: TOnFinishParamsExpr;
  772. Flags: TBuiltInProcFlags;
  773. end;
  774. { TPRFindData }
  775. TPRFindData = record
  776. ErrorPosEl: TPasElement;
  777. Found: TPasElement;
  778. ElScope: TPasScope; // Where Found was found
  779. StartScope: TPasScope; // where the searched started
  780. end;
  781. PPRFindData = ^TPRFindData;
  782. TPasResolverOption = (
  783. proFixCaseOfOverrides, // fix Name of overriding proc/property to the overriden proc/property
  784. proClassPropertyNonStatic, // class property accessor must be non static
  785. proPropertyAsVarParam, // allows to pass a property as a var/out argument
  786. proClassOfIs, // class-of supports is and as operator
  787. proExtClassInstanceNoTypeMembers, // class members of external class cannot be accessed by instance
  788. proOpenAsDynArrays, // open arrays work like dynamic arrays
  789. proProcTypeWithoutIsNested, // proc types can use nested procs without 'is nested'
  790. proMethodAddrAsPointer // can assign @method to a pointer
  791. );
  792. TPasResolverOptions = set of TPasResolverOption;
  793. { TPasResolver }
  794. TPasResolver = Class(TPasTreeContainer)
  795. private
  796. type
  797. TResolveDataListKind = (lkBuiltIn,lkModule);
  798. function GetBaseTypes(bt: TResolverBaseType): TPasUnresolvedSymbolRef; inline;
  799. function GetScopes(Index: integer): TPasScope; inline;
  800. private
  801. FAnonymousElTypePostfix: String;
  802. FBaseTypeChar: TResolverBaseType;
  803. FBaseTypeExtended: TResolverBaseType;
  804. FBaseTypeLength: TResolverBaseType;
  805. FBaseTypes: array[TResolverBaseType] of TPasUnresolvedSymbolRef;
  806. FBaseTypeString: TResolverBaseType;
  807. FDefaultNameSpace: String;
  808. FDefaultScope: TPasDefaultScope;
  809. FDynArrayMaxIndex: int64;
  810. FDynArrayMinIndex: int64;
  811. FLastCreatedData: array[TResolveDataListKind] of TResolveData;
  812. FLastElement: TPasElement;
  813. FLastMsg: string;
  814. FLastMsgArgs: TMessageArgs;
  815. FLastMsgElement: TPasElement;
  816. FLastMsgId: int64;
  817. FLastMsgNumber: integer;
  818. FLastMsgPattern: string;
  819. FLastMsgType: TMessageType;
  820. FLastSourcePos: TPasSourcePos;
  821. FOptions: TPasResolverOptions;
  822. FPendingForwards: TFPList; // list of TPasElement needed to check for forward procs
  823. FRootElement: TPasModule;
  824. FScopeClass_Class: TPasClassScopeClass;
  825. FScopeClass_WithExpr: TPasWithExprScopeClass;
  826. FScopeCount: integer;
  827. FScopes: array of TPasScope; // stack of scopes
  828. FStoreSrcColumns: boolean;
  829. FSubScopeCount: integer;
  830. FSubScopes: array of TPasScope; // stack of scopes
  831. FTopScope: TPasScope;
  832. procedure ClearResolveDataList(Kind: TResolveDataListKind);
  833. function GetBaseTypeNames(bt: TResolverBaseType): string;
  834. protected
  835. const
  836. cIncompatible = High(integer);
  837. cExact = 0;
  838. cCompatible = cExact+1;
  839. cIntToIntConversion = ord(High(TResolverBaseType));
  840. cToFloatConversion = 2*cIntToIntConversion;
  841. cTypeConversion = cExact+10000; // e.g. TObject to Pointer
  842. cLossyConversion = cExact+100000;
  843. cCompatibleWithDefaultParams = cLossyConversion+100000;
  844. type
  845. TFindCallElData = record
  846. Params: TParamsExpr;
  847. Found: TPasElement; // TPasProcedure or TPasUnresolvedSymbolRef(built in proc) or TPasType (typecast)
  848. ElScope, StartScope: TPasScope;
  849. Distance: integer; // compatibility distance
  850. Count: integer;
  851. List: TFPList; // if not nil then collect all found elements here
  852. end;
  853. PFindCallElData = ^TFindCallElData;
  854. TFindOverloadProcData = record
  855. Proc: TPasProcedure;
  856. Args: TFPList; // List of TPasArgument objects
  857. OnlyScope: TPasScope;
  858. Found: TPasProcedure;
  859. ElScope, StartScope: TPasScope;
  860. FoundNonProc: TPasElement;
  861. end;
  862. PFindOverloadProcData = ^TFindOverloadProcData;
  863. procedure OnFindFirstElement(El: TPasElement; ElScope, StartScope: TPasScope;
  864. FindFirstElementData: Pointer; var Abort: boolean); virtual;
  865. procedure OnFindCallElements(El: TPasElement; ElScope, StartScope: TPasScope;
  866. FindProcsData: Pointer; var Abort: boolean); virtual;
  867. procedure OnFindOverloadProc(El: TPasElement; ElScope, StartScope: TPasScope;
  868. FindOverloadData: Pointer; var Abort: boolean); virtual;
  869. protected
  870. procedure SetCurrentParser(AValue: TPasParser); override;
  871. procedure CheckTopScope(ExpectedClass: TPasScopeClass);
  872. function AddIdentifier(Scope: TPasIdentifierScope;
  873. const aName: String; El: TPasElement;
  874. const Kind: TPasIdentifierKind): TPasIdentifier; virtual;
  875. procedure AddModule(El: TPasModule); virtual;
  876. procedure AddSection(El: TPasSection); virtual;
  877. procedure AddType(El: TPasType); virtual;
  878. procedure AddRecordType(El: TPasRecordType); virtual;
  879. procedure AddClassType(El: TPasClassType); virtual;
  880. procedure AddVariable(El: TPasVariable); virtual;
  881. procedure AddEnumType(El: TPasEnumType); virtual;
  882. procedure AddEnumValue(El: TPasEnumValue); virtual;
  883. procedure AddProperty(El: TPasProperty); virtual;
  884. procedure AddProcedure(El: TPasProcedure); virtual;
  885. procedure AddProcedureBody(El: TProcedureBody); virtual;
  886. procedure AddArgument(El: TPasArgument); virtual;
  887. procedure AddFunctionResult(El: TPasResultElement); virtual;
  888. procedure AddExceptOn(El: TPasImplExceptOn); virtual;
  889. procedure ResolveImplBlock(Block: TPasImplBlock); virtual;
  890. procedure ResolveImplElement(El: TPasImplElement); virtual;
  891. procedure ResolveImplCaseOf(CaseOf: TPasImplCaseOf); virtual;
  892. procedure ResolveImplLabelMark(Mark: TPasImplLabelMark); virtual;
  893. procedure ResolveImplForLoop(Loop: TPasImplForLoop); virtual;
  894. procedure ResolveImplWithDo(El: TPasImplWithDo); virtual;
  895. procedure ResolveImplAsm(El: TPasImplAsmStatement); virtual;
  896. procedure ResolveImplAssign(El: TPasImplAssign); virtual;
  897. procedure ResolveImplSimple(El: TPasImplSimple); virtual;
  898. procedure ResolveImplRaise(El: TPasImplRaise); virtual;
  899. procedure ResolveExpr(El: TPasExpr; Access: TResolvedRefAccess); virtual;
  900. procedure ResolveStatementConditionExpr(El: TPasExpr); virtual;
  901. procedure ResolveNameExpr(El: TPasExpr; const aName: string; Access: TResolvedRefAccess); virtual;
  902. procedure ResolveInherited(El: TInheritedExpr; Access: TResolvedRefAccess); virtual;
  903. procedure ResolveInheritedCall(El: TBinaryExpr; Access: TResolvedRefAccess); virtual;
  904. procedure ResolveBinaryExpr(El: TBinaryExpr; Access: TResolvedRefAccess); virtual;
  905. procedure ResolveSubIdent(El: TBinaryExpr; Access: TResolvedRefAccess); virtual;
  906. procedure ResolveParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
  907. procedure ResolveFuncParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
  908. procedure ResolveArrayParamsExpr(Params: TParamsExpr; Access: TResolvedRefAccess); virtual;
  909. procedure ResolveArrayParamsArgs(Params: TParamsExpr;
  910. const ResolvedValue: TPasResolverResult; Access: TResolvedRefAccess); virtual;
  911. function ResolveBracketOperatorClass(Params: TParamsExpr;
  912. const ResolvedValue: TPasResolverResult; ClassScope: TPasClassScope;
  913. Access: TResolvedRefAccess): boolean; virtual;
  914. procedure ResolveSetParamsExpr(Params: TParamsExpr); virtual;
  915. procedure ResolveArrayValues(El: TArrayValues); virtual;
  916. procedure SetResolvedRefAccess(Expr: TPasExpr; Ref: TResolvedReference;
  917. Access: TResolvedRefAccess); virtual;
  918. procedure AccessExpr(Expr: TPasExpr; Access: TResolvedRefAccess);
  919. procedure FinishModule(CurModule: TPasModule); virtual;
  920. procedure FinishUsesClause; virtual;
  921. procedure FinishTypeSection(El: TPasDeclarations); virtual;
  922. procedure FinishTypeDef(El: TPasType); virtual;
  923. procedure FinishEnumType(El: TPasEnumType); virtual;
  924. procedure FinishSetType(El: TPasSetType); virtual;
  925. procedure FinishSubElementType(Parent: TPasElement; El: TPasType); virtual;
  926. procedure FinishRangeType(El: TPasRangeType); virtual;
  927. procedure FinishConstRangeExpr(Left, Right: TPasExpr;
  928. out LeftResolved, RightResolved: TPasResolverResult);
  929. procedure FinishRecordType(El: TPasRecordType); virtual;
  930. procedure FinishClassType(El: TPasClassType); virtual;
  931. procedure FinishClassOfType(El: TPasClassOfType); virtual;
  932. procedure FinishArrayType(El: TPasArrayType); virtual;
  933. procedure FinishConstDef(El: TPasConst); virtual;
  934. procedure FinishProcedure(aProc: TPasProcedure); virtual;
  935. procedure FinishProcedureType(El: TPasProcedureType); virtual;
  936. procedure FinishMethodDeclHeader(Proc: TPasProcedure); virtual;
  937. procedure FinishMethodImplHeader(ImplProc: TPasProcedure); virtual;
  938. procedure FinishExceptOnExpr; virtual;
  939. procedure FinishExceptOnStatement; virtual;
  940. procedure FinishDeclaration(El: TPasElement); virtual;
  941. procedure FinishVariable(El: TPasVariable); virtual;
  942. procedure FinishPropertyOfClass(PropEl: TPasProperty); virtual;
  943. procedure FinishArgument(El: TPasArgument); virtual;
  944. procedure FinishAncestors(aClass: TPasClassType); virtual;
  945. procedure FinishPropertyParamAccess(Params: TParamsExpr;
  946. Prop: TPasProperty);
  947. procedure EmitTypeHints(PosEl: TPasElement; aType: TPasType); virtual;
  948. function EmitElementHints(PosEl, El: TPasElement): boolean; virtual;
  949. procedure ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope: TPasProcedureScope);
  950. procedure CheckConditionExpr(El: TPasExpr; const ResolvedEl: TPasResolverResult); virtual;
  951. procedure CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure);
  952. procedure CheckPendingForwards(El: TPasElement);
  953. procedure ComputeBinaryExpr(Bin: TBinaryExpr;
  954. out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  955. StartEl: TPasElement);
  956. procedure ComputeArrayParams(Params: TParamsExpr;
  957. out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  958. StartEl: TPasElement);
  959. procedure ComputeArrayParams_Class(Params: TParamsExpr;
  960. var ResolvedEl: TPasResolverResult; ClassScope: TPasClassScope;
  961. Flags: TPasResolverComputeFlags; StartEl: TPasElement); virtual;
  962. procedure ComputeFuncParams(Params: TParamsExpr;
  963. out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  964. StartEl: TPasElement);
  965. procedure ComputeSetParams(Params: TParamsExpr;
  966. out ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  967. StartEl: TPasElement);
  968. procedure CheckIsClass(El: TPasElement; const ResolvedEl: TPasResolverResult);
  969. function CheckTypeCastClassInstanceToClass(
  970. const FromClassRes, ToClassRes: TPasResolverResult;
  971. ErrorEl: TPasElement): integer; virtual;
  972. procedure CheckSetLitElCompatible(Left, Right: TPasExpr;
  973. const LHS, RHS: TPasResolverResult);
  974. function CheckIsOrdinal(const ResolvedEl: TPasResolverResult;
  975. ErrorEl: TPasElement; RaiseOnError: boolean): boolean;
  976. procedure CombineArrayLitElTypes(Left, Right: TPasExpr;
  977. var LHS: TPasResolverResult; const RHS: TPasResolverResult);
  978. procedure ConvertRangeToFirstValue(var ResolvedEl: TPasResolverResult);
  979. function IsCharLiteral(const Value: string; ErrorPos: TPasElement): TResolverBaseType; virtual;
  980. function CheckBuiltInMinParamCount(Proc: TResElDataBuiltInProc; Expr: TPasExpr;
  981. MinCount: integer; RaiseOnError: boolean): boolean;
  982. function CheckBuiltInMaxParamCount(Proc: TResElDataBuiltInProc; Params: TParamsExpr;
  983. MaxCount: integer; RaiseOnError: boolean): integer;
  984. function CheckRaiseTypeArgNo(id: int64; ArgNo: integer; Param: TPasExpr;
  985. const ParamResolved: TPasResolverResult; Expected: string; RaiseOnError: boolean): integer;
  986. protected
  987. fExprEvaluator: TResExprEvaluator;
  988. procedure OnExprEvalLog(Sender: TResExprEvaluator; const id: int64;
  989. MsgType: TMessageType; MsgNumber: integer; const Fmt: String;
  990. Args: array of const; PosEl: TPasElement); virtual;
  991. function OnExprEvalIdentifier(Sender: TResExprEvaluator;
  992. Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
  993. function OnExprEvalParams(Sender: TResExprEvaluator;
  994. Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue; virtual;
  995. function EvalBaseTypeCast(Params: TParamsExpr; bt: TResolverBaseType): TResEvalvalue;
  996. function Eval(Expr: TPasExpr; Flags: TResEvalFlags; Store: boolean = true): TResEvalValue;
  997. protected
  998. // custom types (added by descendant resolvers)
  999. function CheckAssignCompatibilityCustom(
  1000. const LHS, RHS: TPasResolverResult; ErrorEl: TPasElement;
  1001. RaiseOnIncompatible: boolean; var Handled: boolean): integer; virtual;
  1002. function CheckEqualCompatibilityCustomType(
  1003. const LHS, RHS: TPasResolverResult; ErrorEl: TPasElement;
  1004. RaiseOnIncompatible: boolean): integer; virtual;
  1005. protected
  1006. // built-in functions
  1007. function BI_Length_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1008. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1009. procedure BI_Length_OnGetCallResult(Proc: TResElDataBuiltInProc;
  1010. Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1011. procedure BI_Length_OnEval(Proc: TResElDataBuiltInProc;
  1012. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
  1013. function BI_SetLength_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1014. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1015. procedure BI_SetLength_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  1016. Params: TParamsExpr); virtual;
  1017. function BI_InExclude_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1018. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1019. procedure BI_InExclude_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  1020. Params: TParamsExpr); virtual;
  1021. function BI_Break_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1022. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1023. function BI_Continue_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1024. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1025. function BI_Exit_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1026. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1027. function BI_IncDec_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1028. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1029. procedure BI_IncDec_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  1030. Params: TParamsExpr); virtual;
  1031. function BI_Assigned_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1032. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1033. procedure BI_Assigned_OnGetCallResult(Proc: TResElDataBuiltInProc;
  1034. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1035. function BI_Chr_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1036. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1037. procedure BI_Chr_OnGetCallResult(Proc: TResElDataBuiltInProc;
  1038. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1039. procedure BI_Chr_OnEval(Proc: TResElDataBuiltInProc;
  1040. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
  1041. function BI_Ord_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1042. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1043. procedure BI_Ord_OnGetCallResult(Proc: TResElDataBuiltInProc;
  1044. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1045. procedure BI_Ord_OnEval(Proc: TResElDataBuiltInProc;
  1046. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
  1047. function BI_LowHigh_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1048. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1049. procedure BI_LowHigh_OnGetCallResult(Proc: TResElDataBuiltInProc;
  1050. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1051. procedure BI_LowHigh_OnEval(Proc: TResElDataBuiltInProc;
  1052. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
  1053. function BI_PredSucc_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1054. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1055. procedure BI_PredSucc_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
  1056. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1057. procedure BI_PredSucc_OnEval(Proc: TResElDataBuiltInProc;
  1058. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
  1059. function BI_Str_CheckParam(IsFunc: boolean; Param: TPasExpr;
  1060. const ParamResolved: TPasResolverResult; ArgNo: integer;
  1061. RaiseOnError: boolean): integer;
  1062. function BI_StrProc_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1063. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1064. procedure BI_StrProc_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  1065. Params: TParamsExpr); virtual;
  1066. function BI_StrFunc_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1067. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1068. procedure BI_StrFunc_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
  1069. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1070. procedure BI_StrFunc_OnEval({%H-}Proc: TResElDataBuiltInProc;
  1071. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue); virtual;
  1072. function BI_ConcatArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1073. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1074. procedure BI_ConcatArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
  1075. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1076. function BI_CopyArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1077. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1078. procedure BI_CopyArray_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
  1079. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1080. function BI_InsertArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1081. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1082. procedure BI_InsertArray_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  1083. Params: TParamsExpr); virtual;
  1084. function BI_DeleteArray_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1085. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1086. procedure BI_DeleteArray_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  1087. Params: TParamsExpr); virtual;
  1088. function BI_TypeInfo_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  1089. Expr: TPasExpr; RaiseOnError: boolean): integer; virtual;
  1090. procedure BI_TypeInfo_OnGetCallResult({%H-}Proc: TResElDataBuiltInProc;
  1091. {%H-}Params: TParamsExpr; out ResolvedEl: TPasResolverResult); virtual;
  1092. public
  1093. constructor Create;
  1094. destructor Destroy; override;
  1095. procedure Clear; virtual; // does not free built-in identifiers
  1096. // overrides of TPasTreeContainer
  1097. function CreateElement(AClass: TPTreeElement; const AName: String;
  1098. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  1099. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  1100. overload; override;
  1101. function CreateElement(AClass: TPTreeElement; const AName: String;
  1102. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  1103. const ASrcPos: TPasSourcePos): TPasElement;
  1104. overload; override;
  1105. function FindElement(const aName: String): TPasElement; override; // used by TPasParser
  1106. function FindElementWithoutParams(const AName: String; ErrorPosEl: TPasElement;
  1107. NoProcsWithArgs: boolean): TPasElement;
  1108. function FindElementWithoutParams(const AName: String; out Data: TPRFindData;
  1109. ErrorPosEl: TPasElement; NoProcsWithArgs: boolean): TPasElement;
  1110. procedure FindLongestUnitName(var El: TPasElement; Expr: TPasExpr);
  1111. procedure IterateElements(const aName: string;
  1112. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  1113. var Abort: boolean); virtual;
  1114. procedure CheckFoundElement(const FindData: TPRFindData;
  1115. Ref: TResolvedReference); virtual;
  1116. function GetVisibilityContext: TPasElement;
  1117. procedure FinishScope(ScopeType: TPasScopeType; El: TPasElement); override;
  1118. function NeedArrayValues(El: TPasElement): boolean; override;
  1119. // built in types and functions
  1120. procedure ClearBuiltInIdentifiers; virtual;
  1121. procedure AddObjFPCBuiltInIdentifiers(
  1122. const TheBaseTypes: TResolveBaseTypes = btAllStandardTypes;
  1123. const TheBaseProcs: TResolverBuiltInProcs = bfAllStandardProcs); virtual;
  1124. function AddBaseType(const aName: string; Typ: TResolverBaseType): TResElDataBaseType;
  1125. function AddCustomBaseType(const aName: string; aClass: TResElDataBaseTypeClass): TPasUnresolvedSymbolRef;
  1126. function IsBaseType(aType: TPasType; BaseType: TResolverBaseType; ResolveAlias: boolean = false): boolean;
  1127. function AddBuiltInProc(const aName: string; Signature: string;
  1128. const GetCallCompatibility: TOnGetCallCompatibility;
  1129. const GetCallResult: TOnGetCallResult;
  1130. const EvalConst: TOnEvalBIFunction = nil;
  1131. const FinishParamsExpr: TOnFinishParamsExpr = nil;
  1132. const BuiltIn: TResolverBuiltInProc = bfCustom;
  1133. const Flags: TBuiltInProcFlags = []): TResElDataBuiltInProc;
  1134. // add extra TResolveData (E.CustomData) to free list
  1135. procedure AddResolveData(El: TPasElement; Data: TResolveData;
  1136. Kind: TResolveDataListKind);
  1137. function CreateReference(DeclEl, RefEl: TPasElement;
  1138. Access: TResolvedRefAccess;
  1139. FindData: PPRFindData = nil): TResolvedReference; virtual;
  1140. // scopes
  1141. function CreateScope(El: TPasElement; ScopeClass: TPasScopeClass): TPasScope; virtual;
  1142. procedure PopScope;
  1143. procedure PushScope(Scope: TPasScope); overload;
  1144. function PushScope(El: TPasElement; ScopeClass: TPasScopeClass): TPasScope; overload;
  1145. function PushModuleDotScope(aModule: TPasModule): TPasModuleDotScope;
  1146. function PushClassDotScope(var CurClassType: TPasClassType): TPasDotClassScope;
  1147. function PushRecordDotScope(CurRecordType: TPasRecordType): TPasDotRecordScope;
  1148. function PushEnumDotScope(CurEnumType: TPasEnumType): TPasDotEnumTypeScope;
  1149. procedure ResetSubScopes(out Depth: integer);
  1150. procedure RestoreSubScopes(Depth: integer);
  1151. // log and messages
  1152. class procedure UnmangleSourceLineNumber(LineNumber: integer;
  1153. out Line, Column: integer);
  1154. class function GetElementSourcePosStr(El: TPasElement): string;
  1155. procedure SetLastMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
  1156. Const Fmt : String; Args : Array of const; PosEl: TPasElement);
  1157. procedure LogMsg(const id: int64; MsgType: TMessageType; MsgNumber: integer;
  1158. const Fmt: String; Args: Array of const; PosEl: TPasElement); overload;
  1159. procedure RaiseMsg(const Id: int64; MsgNumber: integer; const Fmt: String;
  1160. Args: Array of const; ErrorPosEl: TPasElement);
  1161. procedure RaiseNotYetImplemented(id: int64; El: TPasElement; Msg: string = ''); virtual;
  1162. procedure RaiseInternalError(id: int64; const Msg: string = '');
  1163. procedure RaiseInvalidScopeForElement(id: int64; El: TPasElement; const Msg: string = '');
  1164. procedure RaiseIdentifierNotFound(id: int64; Identifier: string; El: TPasElement);
  1165. procedure RaiseXExpectedButYFound(id: int64; const X,Y: string; El: TPasElement);
  1166. procedure RaiseConstantExprExp(id: int64; ErrorEl: TPasElement);
  1167. procedure RaiseRangeCheck(id: int64; ErrorEl: TPasElement);
  1168. procedure RaiseIncompatibleTypeDesc(id: int64; MsgNumber: integer;
  1169. const Args: array of const; const GotDesc, ExpDesc: String; ErrorEl: TPasElement);
  1170. procedure RaiseIncompatibleType(id: int64; MsgNumber: integer;
  1171. const Args: array of const; GotType, ExpType: TPasType; ErrorEl: TPasElement);
  1172. procedure RaiseIncompatibleTypeRes(id: int64; MsgNumber: integer;
  1173. const Args: array of const; const GotType, ExpType: TPasResolverResult;
  1174. ErrorEl: TPasElement);
  1175. procedure RaiseInvalidProcTypeModifier(id: int64; ProcType: TPasProcedureType;
  1176. ptm: TProcTypeModifier; ErrorEl: TPasElement);
  1177. procedure RaiseInvalidProcModifier(id: int64; Proc: TPasProcedure;
  1178. pm: TProcedureModifier; ErrorEl: TPasElement);
  1179. procedure WriteScopes;
  1180. // find value and type of an element
  1181. procedure ComputeElement(El: TPasElement; out ResolvedEl: TPasResolverResult;
  1182. Flags: TPasResolverComputeFlags; StartEl: TPasElement = nil);
  1183. // checking compatibilility
  1184. function IsSameType(TypeA, TypeB: TPasType; ResolveAlias: boolean = false): boolean; // check if it is exactly the same
  1185. function CheckCallProcCompatibility(ProcType: TPasProcedureType;
  1186. Params: TParamsExpr; RaiseOnError: boolean;
  1187. SetReferenceFlags: boolean = false): integer;
  1188. function CheckCallPropertyCompatibility(PropEl: TPasProperty;
  1189. Params: TParamsExpr; RaiseOnError: boolean): integer;
  1190. function CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
  1191. Params: TParamsExpr; RaiseOnError: boolean; EmitHints: boolean = false): integer;
  1192. function CheckParamCompatibility(Expr: TPasExpr; Param: TPasArgument;
  1193. ParamNo: integer; RaiseOnError: boolean; SetReferenceFlags: boolean = false): integer;
  1194. function CheckAssignCompatibilityUserType(
  1195. const LHS, RHS: TPasResolverResult; ErrorEl: TPasElement;
  1196. RaiseOnIncompatible: boolean): integer;
  1197. function CheckAssignCompatibilityArrayType(
  1198. const LHS, RHS: TPasResolverResult; ErrorEl: TPasElement;
  1199. RaiseOnIncompatible: boolean): integer;
  1200. function CheckConstArrayCompatibility(Params: TParamsExpr;
  1201. const ArrayResolved: TPasResolverResult; RaiseOnError: boolean;
  1202. Flags: TPasResolverComputeFlags; StartEl: TPasElement = nil): integer;
  1203. function CheckEqualCompatibilityUserType(
  1204. const TypeA, TypeB: TPasResolverResult; ErrorEl: TPasElement;
  1205. RaiseOnIncompatible: boolean): integer;
  1206. function CheckTypeCast(El: TPasType; Params: TParamsExpr; RaiseOnError: boolean): integer;
  1207. function CheckTypeCastRes(const FromResolved, ToResolved: TPasResolverResult;
  1208. ErrorEl: TPasElement; RaiseOnError: boolean): integer; virtual;
  1209. function CheckTypeCastArray(FromType, ToType: TPasArrayType;
  1210. ErrorEl: TPasElement; RaiseOnError: boolean): integer;
  1211. function CheckSrcIsADstType(
  1212. const ResolvedSrcType, ResolvedDestType: TPasResolverResult;
  1213. ErrorEl: TPasElement): integer;
  1214. function CheckClassIsClass(SrcType, DestType: TPasType;
  1215. ErrorEl: TPasElement): integer; virtual;
  1216. function CheckClassesAreRelated(TypeA, TypeB: TPasType;
  1217. ErrorEl: TPasElement): integer;
  1218. function CheckOverloadProcCompatibility(Proc1, Proc2: TPasProcedure): boolean;
  1219. function CheckProcTypeCompatibility(Proc1, Proc2: TPasProcedureType;
  1220. IsAssign: boolean; ErrorEl: TPasElement; RaiseOnIncompatible: boolean): boolean;
  1221. function CheckProcArgCompatibility(Arg1, Arg2: TPasArgument): boolean;
  1222. function CheckProcArgTypeCompatibility(Arg1, Arg2: TPasType): boolean;
  1223. function CheckCanBeLHS(const ResolvedEl: TPasResolverResult;
  1224. ErrorOnFalse: boolean; ErrorEl: TPasElement): boolean;
  1225. function CheckAssignCompatibility(const LHS, RHS: TPasElement;
  1226. RaiseOnIncompatible: boolean = true): integer;
  1227. procedure CheckAssignExprRange(const LeftResolved: TPasResolverResult; RHS: TPasExpr);
  1228. procedure CheckAssignExprRangeToCustom(const LeftResolved: TPasResolverResult;
  1229. RValue: TResEvalValue; RHS: TPasExpr); virtual;
  1230. function CheckAssignResCompatibility(const LHS, RHS: TPasResolverResult;
  1231. ErrorEl: TPasElement; RaiseOnIncompatible: boolean): integer;
  1232. function CheckEqualElCompatibility(Left, Right: TPasElement;
  1233. ErrorEl: TPasElement; RaiseOnIncompatible: boolean;
  1234. SetReferenceFlags: boolean = false): integer;
  1235. function CheckEqualResCompatibility(const LHS, RHS: TPasResolverResult;
  1236. LErrorEl: TPasElement; RaiseOnIncompatible: boolean;
  1237. RErrorEl: TPasElement = nil): integer;
  1238. function ResolvedElCanBeVarParam(const ResolvedEl: TPasResolverResult): boolean;
  1239. function ResolvedElIsClassInstance(const ResolvedEl: TPasResolverResult): boolean;
  1240. // uility functions
  1241. property BaseTypeNames[bt: TResolverBaseType]: string read GetBaseTypeNames;
  1242. function GetProcTypeDescription(ProcType: TPasProcedureType; UseName: boolean = true; AddPaths: boolean = false): string;
  1243. function GetResolverResultDescription(const T: TPasResolverResult; OnlyType: boolean = false): string;
  1244. function GetTypeDescription(aType: TPasType; AddPath: boolean = false): string;
  1245. function GetTypeDescription(const R: TPasResolverResult; AddPath: boolean = false): string; virtual;
  1246. function GetBaseDescription(const R: TPasResolverResult; AddPath: boolean = false): string; virtual;
  1247. function GetPasPropertyType(El: TPasProperty): TPasType;
  1248. function GetPasPropertyAncestor(El: TPasProperty; WithRedeclarations: boolean = false): TPasProperty;
  1249. function GetPasPropertyGetter(El: TPasProperty): TPasElement;
  1250. function GetPasPropertySetter(El: TPasProperty): TPasElement;
  1251. function GetPasPropertyStored(El: TPasProperty): TPasElement;
  1252. function GetPasClassAncestor(ClassEl: TPasClassType; SkipAlias: boolean): TPasType;
  1253. function GetLoop(El: TPasElement): TPasImplElement;
  1254. function ResolveAliasType(aType: TPasType): TPasType;
  1255. function ExprIsAddrTarget(El: TPasExpr): boolean;
  1256. function IsNameExpr(El: TPasExpr): boolean; inline; // TSelfExpr or TPrimitiveExpr with Kind=pekIdent
  1257. function GetNameExprValue(El: TPasExpr): string; // TSelfExpr or TPrimitiveExpr with Kind=pekIdent
  1258. function GetNextDottedExpr(El: TPasExpr): TPasExpr;
  1259. function GetPathStart(El: TPasExpr): TPasExpr;
  1260. function GetNewInstanceExpr(El: TPasExpr): TPasExpr;
  1261. function ParentNeedsExprResult(El: TPasExpr): boolean;
  1262. function GetReference_NewInstanceClass(Ref: TResolvedReference): TPasClassType;
  1263. function IsDynArray(TypeEl: TPasType): boolean;
  1264. function IsOpenArray(TypeEl: TPasType): boolean;
  1265. function IsDynOrOpenArray(TypeEl: TPasType): boolean;
  1266. function IsVarInit(Expr: TPasExpr): boolean;
  1267. function IsEmptySet(const ResolvedEl: TPasResolverResult): boolean;
  1268. function IsClassMethod(El: TPasElement): boolean;
  1269. function IsExternalClassName(aClass: TPasClassType; const ExtName: string): boolean;
  1270. function IsProcedureType(const ResolvedEl: TPasResolverResult; HasValue: boolean): boolean;
  1271. function IsArrayType(const ResolvedEl: TPasResolverResult): boolean;
  1272. function IsTypeCast(Params: TParamsExpr): boolean;
  1273. function ProcNeedsParams(El: TPasProcedureType): boolean;
  1274. function GetRangeLength(const RangeResolved: TPasResolverResult): MaxPrecInt;
  1275. function EvalRangeLimit(RangeExpr: TPasExpr; Flags: TResEvalFlags;
  1276. EvalLow: boolean; ErrorEl: TPasElement): TResEvalValue; virtual; // compute low() or high()
  1277. function HasTypeInfo(El: TPasType): boolean; virtual;
  1278. function GetActualBaseType(bt: TResolverBaseType): TResolverBaseType; virtual;
  1279. function GetCombinedBoolean(Bool1, Bool2: TResolverBaseType; ErrorEl: TPasElement): TResolverBaseType; virtual;
  1280. function GetCombinedInt(const Int1, Int2: TPasResolverResult; ErrorEl: TPasElement): TResolverBaseType; virtual;
  1281. procedure GetIntegerProps(bt: TResolverBaseType; out Precision: word; out Signed: boolean);
  1282. function GetIntegerRange(bt: TResolverBaseType; out MinVal, MaxVal: int64): boolean;
  1283. function GetIntegerBaseType(Precision: word; Signed: boolean; ErrorEl: TPasElement): TResolverBaseType;
  1284. function GetCombinedChar(const Char1, Char2: TPasResolverResult; ErrorEl: TPasElement): TResolverBaseType; virtual;
  1285. function GetCombinedString(const Str1, Str2: TPasResolverResult; ErrorEl: TPasElement): TResolverBaseType; virtual;
  1286. public
  1287. // options
  1288. property Options: TPasResolverOptions read FOptions write FOptions;
  1289. property AnonymousElTypePostfix: String read FAnonymousElTypePostfix
  1290. write FAnonymousElTypePostfix; // default empty, if set, anonymous element types are named ArrayName+Postfix and added to declarations
  1291. property BaseTypes[bt: TResolverBaseType]: TPasUnresolvedSymbolRef read GetBaseTypes;
  1292. property BaseTypeChar: TResolverBaseType read FBaseTypeChar write FBaseTypeChar;
  1293. property BaseTypeExtended: TResolverBaseType read FBaseTypeExtended write FBaseTypeExtended;
  1294. property BaseTypeString: TResolverBaseType read FBaseTypeString write FBaseTypeString;
  1295. property BaseTypeLength: TResolverBaseType read FBaseTypeLength write FBaseTypeLength;
  1296. property ExprEvaluator: TResExprEvaluator read fExprEvaluator;
  1297. property DynArrayMinIndex: int64 read FDynArrayMinIndex write FDynArrayMinIndex;
  1298. property DynArrayMaxIndex: int64 read FDynArrayMaxIndex write FDynArrayMaxIndex;
  1299. // parsed values
  1300. property DefaultNameSpace: String read FDefaultNameSpace;
  1301. property RootElement: TPasModule read FRootElement;
  1302. // scopes
  1303. property StoreSrcColumns: boolean read FStoreSrcColumns write FStoreSrcColumns; {
  1304. If true Line and Column is mangled together in TPasElement.SourceLineNumber.
  1305. Use method UnmangleSourceLineNumber to extract. }
  1306. property Scopes[Index: integer]: TPasScope read GetScopes;
  1307. property ScopeCount: integer read FScopeCount;
  1308. property TopScope: TPasScope read FTopScope;
  1309. property DefaultScope: TPasDefaultScope read FDefaultScope write FDefaultScope;
  1310. property ScopeClass_Class: TPasClassScopeClass read FScopeClass_Class write FScopeClass_Class;
  1311. property ScopeClass_WithExpr: TPasWithExprScopeClass read FScopeClass_WithExpr write FScopeClass_WithExpr;
  1312. // last element
  1313. property LastElement: TPasElement read FLastElement;
  1314. property LastMsg: string read FLastMsg write FLastMsg;
  1315. property LastMsgArgs: TMessageArgs read FLastMsgArgs write FLastMsgArgs;
  1316. property LastMsgElement: TPasElement read FLastMsgElement write FLastMsgElement;
  1317. property LastMsgId: int64 read FLastMsgId write FLastMsgId;
  1318. property LastMsgNumber: integer read FLastMsgNumber write FLastMsgNumber;
  1319. property LastMsgPattern: string read FLastMsgPattern write FLastMsgPattern;
  1320. property LastMsgType: TMessageType read FLastMsgType write FLastMsgType;
  1321. property LastSourcePos: TPasSourcePos read FLastSourcePos write FLastSourcePos;
  1322. end;
  1323. function GetTreeDbg(El: TPasElement; Indent: integer = 0): string;
  1324. function GetResolverResultDbg(const T: TPasResolverResult): string;
  1325. function GetClassAncestorsDbg(El: TPasClassType): string;
  1326. function ResolverResultFlagsToStr(const Flags: TPasResolverResultFlags): string;
  1327. procedure SetResolverIdentifier(out ResolvedType: TPasResolverResult;
  1328. BaseType: TResolverBaseType; IdentEl: TPasElement;
  1329. TypeEl: TPasType; Flags: TPasResolverResultFlags); overload;
  1330. procedure SetResolverTypeExpr(out ResolvedType: TPasResolverResult;
  1331. BaseType: TResolverBaseType; TypeEl: TPasType;
  1332. Flags: TPasResolverResultFlags); overload;
  1333. procedure SetResolverValueExpr(out ResolvedType: TPasResolverResult;
  1334. BaseType: TResolverBaseType; TypeEl: TPasType; ExprEl: TPasExpr;
  1335. Flags: TPasResolverResultFlags); overload;
  1336. function ProcNeedsImplProc(Proc: TPasProcedure): boolean;
  1337. function ChompDottedIdentifier(const Identifier: string): string;
  1338. function FirstDottedIdentifier(const Identifier: string): string;
  1339. function IsDottedIdentifierPrefix(const Prefix, Identifier: string): boolean;
  1340. {$IF FPC_FULLVERSION<30101}
  1341. function IsValidIdent(const Ident: string; AllowDots: Boolean = False; StrictDots: Boolean = False): Boolean;
  1342. {$ENDIF}
  1343. function dbgs(const Flags: TPasResolverComputeFlags): string; overload;
  1344. function dbgs(const a: TResolvedRefAccess): string;
  1345. function dbgs(const Flags: TResolvedReferenceFlags): string; overload;
  1346. implementation
  1347. function GetTreeDbg(El: TPasElement; Indent: integer): string;
  1348. procedure LineBreak(SubIndent: integer);
  1349. begin
  1350. Inc(Indent,SubIndent);
  1351. Result:=Result+LineEnding+Space(Indent);
  1352. end;
  1353. var
  1354. i, l: Integer;
  1355. begin
  1356. if El=nil then exit('nil');
  1357. Result:=El.Name+':'+El.ClassName+'=';
  1358. if El is TPasExpr then
  1359. begin
  1360. if El.ClassType<>TBinaryExpr then
  1361. Result:=Result+OpcodeStrings[TPasExpr(El).OpCode];
  1362. if El.ClassType=TUnaryExpr then
  1363. Result:=Result+GetTreeDbg(TUnaryExpr(El).Operand,Indent)
  1364. else if El.ClassType=TBinaryExpr then
  1365. Result:=Result+'Left={'+GetTreeDbg(TBinaryExpr(El).left,Indent)+'}'
  1366. +OpcodeStrings[TPasExpr(El).OpCode]
  1367. +'Right={'+GetTreeDbg(TBinaryExpr(El).right,Indent)+'}'
  1368. else if El.ClassType=TPrimitiveExpr then
  1369. Result:=Result+TPrimitiveExpr(El).Value
  1370. else if El.ClassType=TBoolConstExpr then
  1371. Result:=Result+BoolToStr(TBoolConstExpr(El).Value,'true','false')
  1372. else if El.ClassType=TNilExpr then
  1373. Result:=Result+'nil'
  1374. else if El.ClassType=TInheritedExpr then
  1375. Result:=Result+'inherited'
  1376. else if El.ClassType=TSelfExpr then
  1377. Result:=Result+'Self'
  1378. else if El.ClassType=TParamsExpr then
  1379. begin
  1380. LineBreak(2);
  1381. Result:=Result+GetTreeDbg(TParamsExpr(El).Value,Indent)+'(';
  1382. l:=length(TParamsExpr(El).Params);
  1383. if l>0 then
  1384. begin
  1385. inc(Indent,2);
  1386. for i:=0 to l-1 do
  1387. begin
  1388. LineBreak(0);
  1389. Result:=Result+GetTreeDbg(TParamsExpr(El).Params[i],Indent);
  1390. if i<l-1 then
  1391. Result:=Result+','
  1392. end;
  1393. dec(Indent,2);
  1394. end;
  1395. Result:=Result+')';
  1396. end
  1397. else if El.ClassType=TRecordValues then
  1398. begin
  1399. Result:=Result+'(';
  1400. l:=length(TRecordValues(El).Fields);
  1401. if l>0 then
  1402. begin
  1403. inc(Indent,2);
  1404. for i:=0 to l-1 do
  1405. begin
  1406. LineBreak(0);
  1407. Result:=Result+TRecordValues(El).Fields[i].Name+':'
  1408. +GetTreeDbg(TRecordValues(El).Fields[i].ValueExp,Indent);
  1409. if i<l-1 then
  1410. Result:=Result+','
  1411. end;
  1412. dec(Indent,2);
  1413. end;
  1414. Result:=Result+')';
  1415. end
  1416. else if El.ClassType=TArrayValues then
  1417. begin
  1418. Result:=Result+'[';
  1419. l:=length(TArrayValues(El).Values);
  1420. if l>0 then
  1421. begin
  1422. inc(Indent,2);
  1423. for i:=0 to l-1 do
  1424. begin
  1425. LineBreak(0);
  1426. Result:=Result+GetTreeDbg(TArrayValues(El).Values[i],Indent);
  1427. if i<l-1 then
  1428. Result:=Result+','
  1429. end;
  1430. dec(Indent,2);
  1431. end;
  1432. Result:=Result+']';
  1433. end;
  1434. end
  1435. else if El is TPasProcedure then
  1436. begin
  1437. Result:=Result+GetTreeDbg(TPasProcedure(El).ProcType,Indent);
  1438. end
  1439. else if El is TPasProcedureType then
  1440. begin
  1441. if TPasProcedureType(El).IsReferenceTo then
  1442. Result:=Result+' '+ProcTypeModifiers[ptmIsNested];
  1443. Result:=Result+'(';
  1444. l:=TPasProcedureType(El).Args.Count;
  1445. if l>0 then
  1446. begin
  1447. inc(Indent,2);
  1448. for i:=0 to l-1 do
  1449. begin
  1450. LineBreak(0);
  1451. Result:=Result+GetTreeDbg(TPasArgument(TPasProcedureType(El).Args[i]),Indent);
  1452. if i<l-1 then
  1453. Result:=Result+';'
  1454. end;
  1455. dec(Indent,2);
  1456. end;
  1457. Result:=Result+')';
  1458. if El is TPasFunction then
  1459. Result:=Result+':'+GetTreeDbg(TPasFunctionType(TPasFunction(El).ProcType).ResultEl,Indent);
  1460. if TPasProcedureType(El).IsOfObject then
  1461. Result:=Result+' '+ProcTypeModifiers[ptmOfObject];
  1462. if TPasProcedureType(El).IsNested then
  1463. Result:=Result+' '+ProcTypeModifiers[ptmIsNested];
  1464. if cCallingConventions[TPasProcedureType(El).CallingConvention]<>'' then
  1465. Result:=Result+'; '+cCallingConventions[TPasProcedureType(El).CallingConvention];
  1466. end
  1467. else if El.ClassType=TPasResultElement then
  1468. Result:=Result+GetTreeDbg(TPasResultElement(El).ResultType,Indent)
  1469. else if El.ClassType=TPasArgument then
  1470. begin
  1471. if AccessNames[TPasArgument(El).Access]<>'' then
  1472. Result:=Result+AccessNames[TPasArgument(El).Access];
  1473. if TPasArgument(El).ArgType=nil then
  1474. Result:=Result+'untyped'
  1475. else
  1476. Result:=Result+GetTreeDbg(TPasArgument(El).ArgType,Indent);
  1477. end
  1478. else if El.ClassType=TPasUnresolvedSymbolRef then
  1479. begin
  1480. if TPasUnresolvedSymbolRef(El).CustomData is TResElDataBuiltInProc then
  1481. Result:=Result+TResElDataBuiltInProc(TPasUnresolvedSymbolRef(El).CustomData).Signature;
  1482. end;
  1483. end;
  1484. function GetResolverResultDbg(const T: TPasResolverResult): string;
  1485. begin
  1486. Result:='[bt='+ResBaseTypeNames[T.BaseType];
  1487. if T.SubType<>btNone then
  1488. Result:=Result+' Sub='+ResBaseTypeNames[T.SubType];
  1489. Result:=Result
  1490. +' Ident='+GetObjName(T.IdentEl)
  1491. +' Type='+GetObjName(T.TypeEl)
  1492. +' Expr='+GetObjName(T.ExprEl)
  1493. +' Flags='+ResolverResultFlagsToStr(T.Flags)
  1494. +']';
  1495. end;
  1496. function GetClassAncestorsDbg(El: TPasClassType): string;
  1497. function GetClassDesc(C: TPasClassType): string;
  1498. var
  1499. Module: TPasModule;
  1500. begin
  1501. if C.IsExternal then
  1502. Result:='class external '
  1503. else
  1504. Result:='class ';
  1505. Module:=C.GetModule;
  1506. if Module<>nil then
  1507. Result:=Result+Module.Name+'.';
  1508. Result:=Result+C.FullName;
  1509. end;
  1510. var
  1511. Scope, AncestorScope: TPasClassScope;
  1512. AncestorEl: TPasClassType;
  1513. begin
  1514. if El=nil then exit('nil');
  1515. Result:=GetClassDesc(El);
  1516. if El.CustomData is TPasClassScope then
  1517. begin
  1518. Scope:=TPasClassScope(El.CustomData);
  1519. AncestorScope:=Scope.AncestorScope;
  1520. while AncestorScope<>nil do
  1521. begin
  1522. Result:=Result+LineEnding+' ';
  1523. AncestorEl:=AncestorScope.Element as TPasClassType;
  1524. Result:=Result+GetClassDesc(AncestorEl);
  1525. AncestorScope:=AncestorScope.AncestorScope;
  1526. end;
  1527. end;
  1528. end;
  1529. function ResolverResultFlagsToStr(const Flags: TPasResolverResultFlags): string;
  1530. var
  1531. f: TPasResolverResultFlag;
  1532. s: string;
  1533. begin
  1534. Result:='';
  1535. for f in Flags do
  1536. begin
  1537. if Result<>'' then Result:=Result+',';
  1538. str(f,s);
  1539. Result:=Result+s;
  1540. end;
  1541. Result:='['+Result+']';
  1542. end;
  1543. procedure SetResolverIdentifier(out ResolvedType: TPasResolverResult;
  1544. BaseType: TResolverBaseType; IdentEl: TPasElement; TypeEl: TPasType;
  1545. Flags: TPasResolverResultFlags);
  1546. begin
  1547. if IdentEl is TPasExpr then
  1548. raise Exception.Create('20170729101017');
  1549. ResolvedType.BaseType:=BaseType;
  1550. ResolvedType.SubType:=btNone;
  1551. ResolvedType.IdentEl:=IdentEl;
  1552. ResolvedType.TypeEl:=TypeEl;
  1553. ResolvedType.ExprEl:=nil;
  1554. ResolvedType.Flags:=Flags;
  1555. end;
  1556. procedure SetResolverTypeExpr(out ResolvedType: TPasResolverResult;
  1557. BaseType: TResolverBaseType; TypeEl: TPasType; Flags: TPasResolverResultFlags
  1558. );
  1559. begin
  1560. ResolvedType.BaseType:=BaseType;
  1561. ResolvedType.SubType:=btNone;
  1562. ResolvedType.IdentEl:=nil;
  1563. ResolvedType.TypeEl:=TypeEl;
  1564. ResolvedType.ExprEl:=nil;
  1565. ResolvedType.Flags:=Flags;
  1566. end;
  1567. procedure SetResolverValueExpr(out ResolvedType: TPasResolverResult;
  1568. BaseType: TResolverBaseType; TypeEl: TPasType; ExprEl: TPasExpr;
  1569. Flags: TPasResolverResultFlags);
  1570. begin
  1571. ResolvedType.BaseType:=BaseType;
  1572. ResolvedType.SubType:=btNone;
  1573. ResolvedType.IdentEl:=nil;
  1574. ResolvedType.TypeEl:=TypeEl;
  1575. ResolvedType.ExprEl:=ExprEl;
  1576. ResolvedType.Flags:=Flags;
  1577. end;
  1578. function ProcNeedsImplProc(Proc: TPasProcedure): boolean;
  1579. begin
  1580. Result:=true;
  1581. if Proc.IsExternal then exit(false);
  1582. if Proc.IsForward then exit;
  1583. if Proc.Parent.ClassType=TInterfaceSection then exit;
  1584. if Proc.Parent.ClassType=TPasClassType then
  1585. begin
  1586. // a method declaration
  1587. if not Proc.IsAbstract then exit;
  1588. end;
  1589. Result:=false;
  1590. end;
  1591. function ChompDottedIdentifier(const Identifier: string): string;
  1592. var
  1593. p: Integer;
  1594. begin
  1595. Result:=Identifier;
  1596. p:=length(Identifier);
  1597. while (p>0) do
  1598. begin
  1599. if Identifier[p]='.' then
  1600. break;
  1601. dec(p);
  1602. end;
  1603. Result:=LeftStr(Identifier,p-1);
  1604. end;
  1605. function FirstDottedIdentifier(const Identifier: string): string;
  1606. var
  1607. p: SizeInt;
  1608. begin
  1609. p:=Pos('.',Identifier);
  1610. if p<1 then
  1611. Result:=Identifier
  1612. else
  1613. Result:=LeftStr(Identifier,p-1);
  1614. end;
  1615. function IsDottedIdentifierPrefix(const Prefix, Identifier: string): boolean;
  1616. var
  1617. l: Integer;
  1618. begin
  1619. l:=length(Prefix);
  1620. if (l>length(Identifier))
  1621. or (CompareText(Prefix,LeftStr(Identifier,l))<>0) then
  1622. exit(false);
  1623. Result:=(length(Identifier)=l) or (Identifier[l+1]='.');
  1624. end;
  1625. {$IF FPC_FULLVERSION<30101}
  1626. function IsValidIdent(const Ident: string; AllowDots: Boolean;
  1627. StrictDots: Boolean): Boolean;
  1628. const
  1629. Alpha = ['A'..'Z', 'a'..'z', '_'];
  1630. AlphaNum = Alpha + ['0'..'9'];
  1631. Dot = '.';
  1632. var
  1633. First: Boolean;
  1634. I, Len: Integer;
  1635. begin
  1636. Len := Length(Ident);
  1637. if Len < 1 then
  1638. Exit(False);
  1639. First := True;
  1640. for I := 1 to Len do
  1641. begin
  1642. if First then
  1643. begin
  1644. Result := Ident[I] in Alpha;
  1645. First := False;
  1646. end
  1647. else if AllowDots and (Ident[I] = Dot) then
  1648. begin
  1649. if StrictDots then
  1650. begin
  1651. Result := I < Len;
  1652. First := True;
  1653. end;
  1654. end
  1655. else
  1656. Result := Ident[I] in AlphaNum;
  1657. if not Result then
  1658. Break;
  1659. end;
  1660. end;
  1661. {$ENDIF}
  1662. function dbgs(const Flags: TPasResolverComputeFlags): string;
  1663. var
  1664. s: string;
  1665. f: TPasResolverComputeFlag;
  1666. begin
  1667. Result:='';
  1668. for f in Flags do
  1669. if f in Flags then
  1670. begin
  1671. if Result<>'' then Result:=Result+',';
  1672. str(f,s);
  1673. Result:=Result+s;
  1674. end;
  1675. Result:='['+Result+']';
  1676. end;
  1677. function dbgs(const a: TResolvedRefAccess): string;
  1678. begin
  1679. str(a,Result);
  1680. end;
  1681. function dbgs(const Flags: TResolvedReferenceFlags): string;
  1682. var
  1683. s: string;
  1684. f: TResolvedReferenceFlag;
  1685. begin
  1686. Result:='';
  1687. for f in Flags do
  1688. if f in Flags then
  1689. begin
  1690. if Result<>'' then Result:=Result+',';
  1691. str(f,s);
  1692. Result:=Result+s;
  1693. end;
  1694. Result:='['+Result+']';
  1695. end;
  1696. { TPasPropertyScope }
  1697. destructor TPasPropertyScope.Destroy;
  1698. begin
  1699. {$IFDEF VerbosePasResolverMem}
  1700. writeln('TPasPropertyScope.Destroy START ',ClassName);
  1701. {$ENDIF}
  1702. ReleaseAndNil(TPasElement(AncestorProp));
  1703. inherited Destroy;
  1704. {$IFDEF VerbosePasResolverMem}
  1705. writeln('TPasPropertyScope.Destroy END',ClassName);
  1706. {$ENDIF}
  1707. end;
  1708. { TPasEnumTypeScope }
  1709. destructor TPasEnumTypeScope.Destroy;
  1710. begin
  1711. {$IFDEF VerbosePasResolverMem}
  1712. writeln('TPasEnumTypeScope.Destroy START ',ClassName);
  1713. {$ENDIF}
  1714. ReleaseAndNil(TPasElement(CanonicalSet));
  1715. inherited Destroy;
  1716. {$IFDEF VerbosePasResolverMem}
  1717. writeln('TPasEnumTypeScope.Destroy END ',ClassName);
  1718. {$ENDIF}
  1719. end;
  1720. { TPasDotIdentifierScope }
  1721. function TPasDotIdentifierScope.FindIdentifier(const Identifier: String
  1722. ): TPasIdentifier;
  1723. begin
  1724. Result:=IdentifierScope.FindIdentifier(Identifier);
  1725. end;
  1726. procedure TPasDotIdentifierScope.IterateElements(const aName: string;
  1727. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  1728. Data: Pointer; var Abort: boolean);
  1729. begin
  1730. IdentifierScope.IterateElements(aName, StartScope, OnIterateElement, Data, Abort);
  1731. end;
  1732. procedure TPasDotIdentifierScope.WriteIdentifiers(Prefix: string);
  1733. begin
  1734. IdentifierScope.WriteIdentifiers(Prefix);
  1735. end;
  1736. { TPasWithExprScope }
  1737. class function TPasWithExprScope.IsStoredInElement: boolean;
  1738. begin
  1739. Result:=false;
  1740. end;
  1741. class function TPasWithExprScope.FreeOnPop: boolean;
  1742. begin
  1743. Result:=false;
  1744. end;
  1745. procedure TPasWithExprScope.IterateElements(const aName: string;
  1746. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  1747. Data: Pointer; var Abort: boolean);
  1748. begin
  1749. Scope.IterateElements(aName, StartScope, OnIterateElement, Data, Abort);
  1750. end;
  1751. procedure TPasWithExprScope.WriteIdentifiers(Prefix: string);
  1752. begin
  1753. writeln(Prefix+'WithExpr: '+GetTreeDbg(Expr,length(Prefix)));
  1754. Scope.WriteIdentifiers(Prefix);
  1755. end;
  1756. { TPasWithScope }
  1757. constructor TPasWithScope.Create;
  1758. begin
  1759. inherited Create;
  1760. ExpressionScopes:=TObjectList.Create(true);
  1761. end;
  1762. destructor TPasWithScope.Destroy;
  1763. begin
  1764. {$IFDEF VerbosePasResolverMem}
  1765. writeln('TPasWithScope.Destroy START ',ClassName);
  1766. {$ENDIF}
  1767. FreeAndNil(ExpressionScopes);
  1768. inherited Destroy;
  1769. {$IFDEF VerbosePasResolverMem}
  1770. writeln('TPasWithScope.Destroy END ',ClassName);
  1771. {$ENDIF}
  1772. end;
  1773. { TPasProcedureScope }
  1774. function TPasProcedureScope.FindIdentifier(const Identifier: String
  1775. ): TPasIdentifier;
  1776. begin
  1777. Result:=inherited FindIdentifier(Identifier);
  1778. if Result<>nil then exit;
  1779. if ClassScope<>nil then
  1780. Result:=ClassScope.FindIdentifier(Identifier);
  1781. end;
  1782. procedure TPasProcedureScope.IterateElements(const aName: string;
  1783. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  1784. Data: Pointer; var Abort: boolean);
  1785. begin
  1786. inherited IterateElements(aName, StartScope, OnIterateElement, Data, Abort);
  1787. if Abort then exit;
  1788. if ClassScope<>nil then
  1789. ClassScope.IterateElements(aName, StartScope, OnIterateElement, Data, Abort);
  1790. end;
  1791. function TPasProcedureScope.GetSelfScope: TPasProcedureScope;
  1792. var
  1793. Proc: TPasProcedure;
  1794. begin
  1795. Result:=Self;
  1796. repeat
  1797. if Result.ClassScope<>nil then exit;
  1798. Proc:=TPasProcedure(Element);
  1799. if not (Proc.Parent is TProcedureBody) then exit(nil);
  1800. Proc:=Proc.Parent.Parent as TPasProcedure;
  1801. Result:=TPasProcedureScope(Proc.CustomData);
  1802. until false;
  1803. end;
  1804. procedure TPasProcedureScope.WriteIdentifiers(Prefix: string);
  1805. begin
  1806. inherited WriteIdentifiers(Prefix);
  1807. if ClassScope<>nil then
  1808. ClassScope.WriteIdentifiers(Prefix+' ');
  1809. end;
  1810. destructor TPasProcedureScope.Destroy;
  1811. begin
  1812. {$IFDEF VerbosePasResolverMem}
  1813. writeln('TPasProcedureScope.Destroy START ',ClassName);
  1814. {$ENDIF}
  1815. inherited Destroy;
  1816. ReleaseAndNil(TPasElement(SelfArg));
  1817. {$IFDEF VerbosePasResolverMem}
  1818. writeln('TPasProcedureScope.Destroy END ',ClassName);
  1819. {$ENDIF}
  1820. end;
  1821. { TPasClassScope }
  1822. destructor TPasClassScope.Destroy;
  1823. begin
  1824. ReleaseAndNil(TPasElement(CanonicalClassOf));
  1825. inherited Destroy;
  1826. end;
  1827. function TPasClassScope.FindIdentifier(const Identifier: String
  1828. ): TPasIdentifier;
  1829. begin
  1830. Result:=inherited FindIdentifier(Identifier);
  1831. if Result<>nil then exit;
  1832. if AncestorScope<>nil then
  1833. Result:=AncestorScope.FindIdentifier(Identifier);
  1834. end;
  1835. procedure TPasClassScope.IterateElements(const aName: string;
  1836. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  1837. Data: Pointer; var Abort: boolean);
  1838. begin
  1839. inherited IterateElements(aName, StartScope, OnIterateElement, Data, Abort);
  1840. if Abort then exit;
  1841. if AncestorScope<>nil then
  1842. AncestorScope.IterateElements(aName,StartScope,OnIterateElement,Data,Abort);
  1843. end;
  1844. procedure TPasClassScope.WriteIdentifiers(Prefix: string);
  1845. begin
  1846. inherited WriteIdentifiers(Prefix);
  1847. if AncestorScope<>nil then
  1848. AncestorScope.WriteIdentifiers(Prefix+' ');
  1849. end;
  1850. { TPasDotClassScope }
  1851. procedure TPasDotClassScope.SetClassScope(AValue: TPasClassScope);
  1852. begin
  1853. if FClassScope=AValue then Exit;
  1854. FClassScope:=AValue;
  1855. IdentifierScope:=AValue;
  1856. end;
  1857. { TPasIdentifier }
  1858. procedure TPasIdentifier.SetElement(AValue: TPasElement);
  1859. begin
  1860. if FElement=AValue then Exit;
  1861. if Element<>nil then
  1862. Element.Release;
  1863. FElement:=AValue;
  1864. if Element<>nil then
  1865. Element.AddRef;
  1866. end;
  1867. destructor TPasIdentifier.Destroy;
  1868. begin
  1869. {$IFDEF VerbosePasResolverMem}
  1870. writeln('TPasIdentifier.Destroy START ',ClassName,' "',Identifier,'"');
  1871. {$ENDIF}
  1872. Element:=nil;
  1873. inherited Destroy;
  1874. {$IFDEF VerbosePasResolverMem}
  1875. writeln('TPasIdentifier.Destroy END ',ClassName);
  1876. {$ENDIF}
  1877. end;
  1878. { EPasResolve }
  1879. procedure EPasResolve.SetPasElement(AValue: TPasElement);
  1880. begin
  1881. if FPasElement=AValue then Exit;
  1882. if PasElement<>nil then
  1883. PasElement.Release;
  1884. FPasElement:=AValue;
  1885. if PasElement<>nil then
  1886. PasElement.AddRef;
  1887. end;
  1888. destructor EPasResolve.Destroy;
  1889. begin
  1890. {$IFDEF VerbosePasResolverMem}
  1891. writeln('EPasResolve.Destroy START ',ClassName);
  1892. {$ENDIF}
  1893. PasElement:=nil;
  1894. inherited Destroy;
  1895. {$IFDEF VerbosePasResolverMem}
  1896. writeln('EPasResolve.Destroy END ',ClassName);
  1897. {$ENDIF}
  1898. end;
  1899. { TResolvedReference }
  1900. procedure TResolvedReference.SetDeclaration(AValue: TPasElement);
  1901. begin
  1902. if FDeclaration=AValue then Exit;
  1903. if Declaration<>nil then
  1904. Declaration.Release;
  1905. FDeclaration:=AValue;
  1906. if Declaration<>nil then
  1907. Declaration.AddRef;
  1908. end;
  1909. destructor TResolvedReference.Destroy;
  1910. begin
  1911. {$IFDEF VerbosePasResolverMem}
  1912. writeln('TResolvedReference.Destroy START ',ClassName);
  1913. {$ENDIF}
  1914. Declaration:=nil;
  1915. FreeAndNil(Context);
  1916. inherited Destroy;
  1917. {$IFDEF VerbosePasResolverMem}
  1918. writeln('TResolvedReference.Destroy END ',ClassName);
  1919. {$ENDIF}
  1920. end;
  1921. { TPasSubScope }
  1922. class function TPasSubScope.IsStoredInElement: boolean;
  1923. begin
  1924. Result:=false;
  1925. end;
  1926. { TPasModuleDotScope }
  1927. procedure TPasModuleDotScope.OnInternalIterate(El: TPasElement; ElScope,
  1928. StartScope: TPasScope; Data: Pointer; var Abort: boolean);
  1929. var
  1930. FilterData: PPasIterateFilterData absolute Data;
  1931. begin
  1932. if (El.ClassType=TPasModule) or (El.ClassType=TPasUsesUnit) then
  1933. exit; // skip used units
  1934. // call the original iterator
  1935. FilterData^.OnIterate(El,ElScope,StartScope,FilterData^.Data,Abort);
  1936. end;
  1937. procedure TPasModuleDotScope.SetModule(AValue: TPasModule);
  1938. begin
  1939. if FModule=AValue then Exit;
  1940. if Module<>nil then
  1941. Module.Release;
  1942. FModule:=AValue;
  1943. if Module<>nil then
  1944. Module.AddRef;
  1945. end;
  1946. destructor TPasModuleDotScope.Destroy;
  1947. begin
  1948. {$IFDEF VerbosePasResolverMem}
  1949. writeln('TPasSubModuleScope.Destroy START ',ClassName);
  1950. {$ENDIF}
  1951. Module:=nil;
  1952. inherited Destroy;
  1953. {$IFDEF VerbosePasResolverMem}
  1954. writeln('TPasSubModuleScope.Destroy END ',ClassName);
  1955. {$ENDIF}
  1956. end;
  1957. function TPasModuleDotScope.FindIdentifier(const Identifier: String
  1958. ): TPasIdentifier;
  1959. begin
  1960. if ImplementationScope<>nil then
  1961. begin
  1962. Result:=ImplementationScope.FindLocalIdentifier(Identifier);
  1963. if (Result<>nil) and (Result.Element.ClassType<>TPasModule) then
  1964. exit;
  1965. end;
  1966. if InterfaceScope<>nil then
  1967. Result:=InterfaceScope.FindLocalIdentifier(Identifier)
  1968. else
  1969. Result:=nil;
  1970. end;
  1971. procedure TPasModuleDotScope.IterateElements(const aName: string;
  1972. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  1973. Data: Pointer; var Abort: boolean);
  1974. var
  1975. FilterData: TPasIterateFilterData;
  1976. begin
  1977. FilterData.OnIterate:=OnIterateElement;
  1978. FilterData.Data:=Data;
  1979. if ImplementationScope<>nil then
  1980. begin
  1981. ImplementationScope.IterateLocalElements(aName,StartScope,@OnInternalIterate,@FilterData,Abort);
  1982. if Abort then exit;
  1983. end;
  1984. if InterfaceScope<>nil then
  1985. InterfaceScope.IterateLocalElements(aName,StartScope,@OnInternalIterate,@FilterData,Abort);
  1986. end;
  1987. procedure TPasModuleDotScope.WriteIdentifiers(Prefix: string);
  1988. begin
  1989. if ImplementationScope<>nil then
  1990. ImplementationScope.WriteIdentifiers(Prefix+' ');
  1991. if InterfaceScope<>nil then
  1992. InterfaceScope.WriteIdentifiers(Prefix+' ');
  1993. end;
  1994. { TPasSectionScope }
  1995. constructor TPasSectionScope.Create;
  1996. begin
  1997. inherited Create;
  1998. UsesScopes:=TFPList.Create;
  1999. end;
  2000. destructor TPasSectionScope.Destroy;
  2001. begin
  2002. {$IFDEF VerbosePasResolverMem}
  2003. writeln('TPasSectionScope.Destroy START ',ClassName);
  2004. {$ENDIF}
  2005. FreeAndNil(UsesScopes);
  2006. inherited Destroy;
  2007. {$IFDEF VerbosePasResolverMem}
  2008. writeln('TPasSectionScope.Destroy END ',ClassName);
  2009. {$ENDIF}
  2010. end;
  2011. function TPasSectionScope.FindIdentifier(const Identifier: String
  2012. ): TPasIdentifier;
  2013. var
  2014. i: Integer;
  2015. UsesScope: TPasIdentifierScope;
  2016. begin
  2017. Result:=inherited FindIdentifier(Identifier);
  2018. if Result<>nil then
  2019. exit;
  2020. for i:=0 to UsesScopes.Count-1 do
  2021. begin
  2022. UsesScope:=TPasIdentifierScope(UsesScopes[i]);
  2023. {$IFDEF VerbosePasResolver}
  2024. writeln('TPasSectionScope.FindIdentifier "',Identifier,'" in used unit ',GetObjName(UsesScope.Element));
  2025. {$ENDIF}
  2026. Result:=UsesScope.FindLocalIdentifier(Identifier);
  2027. if Result<>nil then exit;
  2028. end;
  2029. end;
  2030. procedure TPasSectionScope.IterateElements(const aName: string;
  2031. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  2032. Data: Pointer; var Abort: boolean);
  2033. var
  2034. i: Integer;
  2035. UsesScope: TPasIdentifierScope;
  2036. begin
  2037. inherited IterateElements(aName, StartScope, OnIterateElement, Data, Abort);
  2038. if Abort then exit;
  2039. for i:=0 to UsesScopes.Count-1 do
  2040. begin
  2041. UsesScope:=TPasIdentifierScope(UsesScopes[i]);
  2042. {$IFDEF VerbosePasResolver}
  2043. writeln('TPasSectionScope.IterateElements "',aName,'" in used unit ',GetObjName(UsesScope.Element));
  2044. {$ENDIF}
  2045. UsesScope.IterateLocalElements(aName,StartScope,OnIterateElement,Data,Abort);
  2046. if Abort then exit;
  2047. end;
  2048. end;
  2049. procedure TPasSectionScope.WriteIdentifiers(Prefix: string);
  2050. var
  2051. i: Integer;
  2052. UsesScope: TPasIdentifierScope;
  2053. begin
  2054. inherited WriteIdentifiers(Prefix);
  2055. for i:=0 to UsesScopes.Count-1 do
  2056. begin
  2057. UsesScope:=TPasIdentifierScope(UsesScopes[i]);
  2058. writeln(Prefix+'Uses: '+GetObjName(UsesScope.Element));
  2059. end;
  2060. end;
  2061. { TPasModuleScope }
  2062. procedure TPasModuleScope.IterateElements(const aName: string;
  2063. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  2064. Data: Pointer; var Abort: boolean);
  2065. begin
  2066. if CompareText(aName,FirstName)<>0 then exit;
  2067. OnIterateElement(Element,Self,StartScope,Data,Abort);
  2068. end;
  2069. { TPasDefaultScope }
  2070. class function TPasDefaultScope.IsStoredInElement: boolean;
  2071. begin
  2072. Result:=false;
  2073. end;
  2074. { TPasScope }
  2075. class function TPasScope.IsStoredInElement: boolean;
  2076. begin
  2077. Result:=true;
  2078. end;
  2079. class function TPasScope.FreeOnPop: boolean;
  2080. begin
  2081. Result:=not IsStoredInElement;
  2082. end;
  2083. procedure TPasScope.IterateElements(const aName: string; StartScope: TPasScope;
  2084. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  2085. var Abort: boolean);
  2086. begin
  2087. if aName='' then ;
  2088. if StartScope=nil then ;
  2089. if Data=nil then ;
  2090. if OnIterateElement=nil then ;
  2091. if Abort then ;
  2092. end;
  2093. procedure TPasScope.WriteIdentifiers(Prefix: string);
  2094. begin
  2095. writeln(Prefix,'Element: ',GetObjName(Element));
  2096. end;
  2097. { TPasIdentifierScope }
  2098. // inline
  2099. function TPasIdentifierScope.FindLocalIdentifier(const Identifier: String
  2100. ): TPasIdentifier;
  2101. var
  2102. LoName: String;
  2103. begin
  2104. LoName:=lowercase(Identifier);
  2105. Result:=TPasIdentifier(FItems.Find(LoName));
  2106. end;
  2107. procedure TPasIdentifierScope.OnClearItem(Item, Dummy: pointer);
  2108. var
  2109. PasIdentifier: TPasIdentifier absolute Item;
  2110. Ident: TPasIdentifier;
  2111. begin
  2112. if Dummy=nil then ;
  2113. //writeln('TPasIdentifierScope.OnClearItem ',PasIdentifier.Identifier+':'+PasIdentifier.ClassName);
  2114. while PasIdentifier<>nil do
  2115. begin
  2116. Ident:=PasIdentifier;
  2117. PasIdentifier:=PasIdentifier.NextSameIdentifier;
  2118. Ident.Free;
  2119. end;
  2120. end;
  2121. procedure TPasIdentifierScope.OnWriteItem(Item, Dummy: pointer);
  2122. var
  2123. PasIdentifier: TPasIdentifier absolute Item;
  2124. Prefix: String;
  2125. begin
  2126. Prefix:=AnsiString(Dummy);
  2127. while PasIdentifier<>nil do
  2128. begin
  2129. writeln(Prefix,'Identifier="',PasIdentifier.Identifier,'" Element=',GetObjName(PasIdentifier.Element));
  2130. PasIdentifier:=PasIdentifier.NextSameIdentifier;
  2131. end;
  2132. end;
  2133. procedure TPasIdentifierScope.InternalAdd(Item: TPasIdentifier);
  2134. var
  2135. Index: Integer;
  2136. OldItem: TPasIdentifier;
  2137. LoName: string;
  2138. begin
  2139. LoName:=lowercase(Item.Identifier);
  2140. Index:=FItems.FindIndexOf(LoName);
  2141. {$IFDEF VerbosePasResolver}
  2142. if Item.Owner<>nil then
  2143. raise Exception.Create('20160925184110');
  2144. Item.Owner:=Self;
  2145. {$ENDIF}
  2146. //writeln(' Index=',Index);
  2147. if Index>=0 then
  2148. begin
  2149. // insert LIFO - last in, first out
  2150. OldItem:=TPasIdentifier(FItems.List^[Index].Data);
  2151. {$IFDEF VerbosePasResolver}
  2152. if lowercase(OldItem.Identifier)<>LoName then
  2153. raise Exception.Create('20160925183438');
  2154. {$ENDIF}
  2155. Item.NextSameIdentifier:=OldItem;
  2156. FItems.List^[Index].Data:=Item;
  2157. end
  2158. else
  2159. begin
  2160. FItems.Add(LoName, Item);
  2161. {$IFDEF VerbosePasResolver}
  2162. if FindIdentifier(Item.Identifier)<>Item then
  2163. raise Exception.Create('20160925183849');
  2164. {$ENDIF}
  2165. end;
  2166. end;
  2167. constructor TPasIdentifierScope.Create;
  2168. begin
  2169. FItems:=TFPHashList.Create;
  2170. end;
  2171. destructor TPasIdentifierScope.Destroy;
  2172. begin
  2173. {$IFDEF VerbosePasResolverMem}
  2174. writeln('TPasIdentifierScope.Destroy START ',ClassName);
  2175. {$ENDIF}
  2176. FItems.ForEachCall(@OnClearItem,nil);
  2177. FItems.Clear;
  2178. FreeAndNil(FItems);
  2179. inherited Destroy;
  2180. {$IFDEF VerbosePasResolverMem}
  2181. writeln('TPasIdentifierScope.Destroy END ',ClassName);
  2182. {$ENDIF}
  2183. end;
  2184. function TPasIdentifierScope.FindIdentifier(const Identifier: String
  2185. ): TPasIdentifier;
  2186. begin
  2187. Result:=FindLocalIdentifier(Identifier);
  2188. {$IFDEF VerbosePasResolver}
  2189. if (Result<>nil) and (Result.Owner<>Self) then
  2190. begin
  2191. writeln('TPasIdentifierScope.FindIdentifier Result.Owner<>Self Owner='+GetObjName(Result.Owner));
  2192. raise Exception.Create('20160925184159');
  2193. end;
  2194. {$ENDIF}
  2195. end;
  2196. function TPasIdentifierScope.RemoveLocalIdentifier(El: TPasElement): boolean;
  2197. var
  2198. Identifier, PrevIdentifier: TPasIdentifier;
  2199. LoName: string;
  2200. begin
  2201. LoName:=lowercase(El.Name);
  2202. Identifier:=TPasIdentifier(FItems.Find(LoName));
  2203. FindLocalIdentifier(El.Name);
  2204. PrevIdentifier:=nil;
  2205. Result:=false;
  2206. while Identifier<>nil do
  2207. begin
  2208. {$IFDEF VerbosePasResolver}
  2209. if (Identifier.Owner<>Self) then
  2210. raise Exception.Create('20160925184159');
  2211. {$ENDIF}
  2212. if Identifier.Element=El then
  2213. begin
  2214. if PrevIdentifier<>nil then
  2215. begin
  2216. PrevIdentifier.NextSameIdentifier:=Identifier.NextSameIdentifier;
  2217. Identifier.Free;
  2218. Identifier:=PrevIdentifier.NextSameIdentifier;
  2219. end
  2220. else
  2221. begin
  2222. FItems.Remove(Identifier);
  2223. PrevIdentifier:=Identifier;
  2224. Identifier:=Identifier.NextSameIdentifier;
  2225. PrevIdentifier.Free;
  2226. PrevIdentifier:=nil;
  2227. if Identifier<>nil then
  2228. FItems.Add(Loname,Identifier);
  2229. end;
  2230. Result:=true;
  2231. continue;
  2232. end;
  2233. PrevIdentifier:=Identifier;
  2234. Identifier:=Identifier.NextSameIdentifier;
  2235. end;
  2236. end;
  2237. function TPasIdentifierScope.AddIdentifier(const Identifier: String;
  2238. El: TPasElement; const Kind: TPasIdentifierKind): TPasIdentifier;
  2239. var
  2240. Item: TPasIdentifier;
  2241. begin
  2242. //writeln('TPasIdentifierScope.AddIdentifier Identifier="',Identifier,'" El=',GetObjName(El));
  2243. Item:=TPasIdentifier.Create;
  2244. Item.Identifier:=Identifier;
  2245. Item.Element:=El;
  2246. Item.Kind:=Kind;
  2247. InternalAdd(Item);
  2248. //writeln('TPasIdentifierScope.AddIdentifier END');
  2249. Result:=Item;
  2250. end;
  2251. function TPasIdentifierScope.FindElement(const aName: string): TPasElement;
  2252. var
  2253. Item: TPasIdentifier;
  2254. begin
  2255. //writeln('TPasIdentifierScope.FindElement "',aName,'"');
  2256. Item:=FindIdentifier(aName);
  2257. if Item=nil then
  2258. Result:=nil
  2259. else
  2260. Result:=Item.Element;
  2261. //writeln('TPasIdentifierScope.FindElement Found="',GetObjName(Result),'"');
  2262. end;
  2263. procedure TPasIdentifierScope.IterateLocalElements(const aName: string;
  2264. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  2265. Data: Pointer; var Abort: boolean);
  2266. var
  2267. Item: TPasIdentifier;
  2268. {$IFDEF VerbosePasResolver}
  2269. OldElement: TPasElement;
  2270. {$ENDIF}
  2271. begin
  2272. Item:=FindLocalIdentifier(aName);
  2273. while Item<>nil do
  2274. begin
  2275. //writeln('TPasIdentifierScope.IterateLocalElements ',ClassName,' ',Item.Identifier,' ',GetObjName(Item.Element));
  2276. {$IFDEF VerbosePasResolver}
  2277. OldElement:=Item.Element;
  2278. {$ENDIF}
  2279. OnIterateElement(Item.Element,Self,StartScope,Data,Abort);
  2280. {$IFDEF VerbosePasResolver}
  2281. if OldElement<>Item.Element then
  2282. raise Exception.Create('20160925183503');
  2283. {$ENDIF}
  2284. if Abort then exit;
  2285. Item:=Item.NextSameIdentifier;
  2286. end;
  2287. end;
  2288. procedure TPasIdentifierScope.IterateElements(const aName: string;
  2289. StartScope: TPasScope; const OnIterateElement: TIterateScopeElement;
  2290. Data: Pointer; var Abort: boolean);
  2291. begin
  2292. IterateLocalElements(aName,StartScope,OnIterateElement,Data,Abort);
  2293. end;
  2294. procedure TPasIdentifierScope.WriteIdentifiers(Prefix: string);
  2295. begin
  2296. inherited WriteIdentifiers(Prefix);
  2297. Prefix:=Prefix+' ';
  2298. FItems.ForEachCall(@OnWriteItem,Pointer(Prefix));
  2299. end;
  2300. { TPasResolver }
  2301. // inline
  2302. function TPasResolver.GetBaseTypes(bt: TResolverBaseType
  2303. ): TPasUnresolvedSymbolRef;
  2304. begin
  2305. Result:=FBaseTypes[bt];
  2306. end;
  2307. // inline
  2308. function TPasResolver.GetScopes(Index: integer): TPasScope;
  2309. begin
  2310. Result:=FScopes[Index];
  2311. end;
  2312. // inline
  2313. function TPasResolver.IsNameExpr(El: TPasExpr): boolean;
  2314. begin
  2315. Result:=(El.ClassType=TSelfExpr)
  2316. or ((El.ClassType=TPrimitiveExpr) and (TPrimitiveExpr(El).Kind=pekIdent));
  2317. end;
  2318. function TPasResolver.GetNameExprValue(El: TPasExpr): string;
  2319. begin
  2320. if El=nil then
  2321. Result:=''
  2322. else if El.ClassType=TPrimitiveExpr then
  2323. begin
  2324. if TPrimitiveExpr(El).Kind=pekIdent then
  2325. Result:=TPrimitiveExpr(El).Value
  2326. else
  2327. Result:='';
  2328. end
  2329. else if El.ClassType=TSelfExpr then
  2330. Result:='self'
  2331. else
  2332. Result:='';
  2333. end;
  2334. function TPasResolver.GetNextDottedExpr(El: TPasExpr): TPasExpr;
  2335. // returns TSelfExpr or TPrimitiveExpr (Kind=pekIdent)
  2336. var
  2337. Bin: TBinaryExpr;
  2338. C: TClass;
  2339. begin
  2340. Result:=nil;
  2341. if El=nil then exit;
  2342. repeat
  2343. if not (El.Parent is TBinaryExpr) then exit;
  2344. Bin:=TBinaryExpr(El.Parent);
  2345. if Bin.OpCode<>eopSubIdent then exit;
  2346. if El=Bin.right then
  2347. El:=Bin
  2348. else
  2349. begin
  2350. El:=Bin.right;
  2351. // find left most
  2352. repeat
  2353. C:=El.ClassType;
  2354. if C=TSelfExpr then
  2355. exit(El)
  2356. else if C=TPrimitiveExpr then
  2357. begin
  2358. if TPrimitiveExpr(El).Kind<>pekIdent then
  2359. RaiseNotYetImplemented(20170502163825,El);
  2360. exit(El);
  2361. end
  2362. else if C=TBinaryExpr then
  2363. begin
  2364. if TBinaryExpr(El).OpCode<>eopSubIdent then
  2365. RaiseNotYetImplemented(20170502163718,El);
  2366. El:=TBinaryExpr(El).left;
  2367. end
  2368. else if C=TParamsExpr then
  2369. begin
  2370. if not (TParamsExpr(El).Kind in [pekFuncParams,pekArrayParams]) then
  2371. RaiseNotYetImplemented(20170502163908,El);
  2372. El:=TParamsExpr(El).Value;
  2373. end;
  2374. until El=nil;
  2375. RaiseNotYetImplemented(20170502163953,Bin);
  2376. end;
  2377. until false;
  2378. end;
  2379. function TPasResolver.GetPathStart(El: TPasExpr): TPasExpr;
  2380. // get leftmost name element (e.g. TPrimitiveExpr or TSelfExpr)
  2381. // nil if not found
  2382. var
  2383. C: TClass;
  2384. begin
  2385. Result:=nil;
  2386. while El<>nil do
  2387. begin
  2388. C:=El.ClassType;
  2389. if C=TPrimitiveExpr then
  2390. exit(El)
  2391. else if C=TSelfExpr then
  2392. exit(El)
  2393. else if C=TBinaryExpr then
  2394. begin
  2395. if TBinaryExpr(El).OpCode=eopSubIdent then
  2396. El:=TBinaryExpr(El).left
  2397. else
  2398. exit;
  2399. end
  2400. else if C=TParamsExpr then
  2401. El:=TParamsExpr(El).Value
  2402. else
  2403. exit;
  2404. end;
  2405. end;
  2406. function TPasResolver.GetNewInstanceExpr(El: TPasExpr): TPasExpr;
  2407. // if the expression is a constructor newinstance call,
  2408. // return the element referring the constructor
  2409. // else nil
  2410. var
  2411. C: TClass;
  2412. begin
  2413. Result:=nil;
  2414. while El<>nil do
  2415. begin
  2416. if (El.CustomData is TResolvedReference)
  2417. and (rrfNewInstance in TResolvedReference(El.CustomData).Flags) then
  2418. exit(El);
  2419. C:=El.ClassType;
  2420. if C=TBinaryExpr then
  2421. begin
  2422. if TBinaryExpr(El).OpCode=eopSubIdent then
  2423. El:=TBinaryExpr(El).right
  2424. else
  2425. exit;
  2426. end
  2427. else if C=TParamsExpr then
  2428. El:=TParamsExpr(El).Value
  2429. else
  2430. exit;
  2431. end;
  2432. end;
  2433. procedure TPasResolver.ClearResolveDataList(Kind: TResolveDataListKind);
  2434. var
  2435. El: TPasElement;
  2436. RData: TResolveData;
  2437. begin
  2438. // clear CustomData
  2439. while FLastCreatedData[Kind]<>nil do
  2440. begin
  2441. RData:=FLastCreatedData[Kind];
  2442. El:=RData.Element;
  2443. El.CustomData:=nil;
  2444. FLastCreatedData[Kind]:=RData.Next;
  2445. RData.Free;
  2446. end;
  2447. end;
  2448. function TPasResolver.GetBaseTypeNames(bt: TResolverBaseType): string;
  2449. begin
  2450. if FBaseTypes[bt]<>nil then
  2451. Result:=FBaseTypes[bt].Name
  2452. else
  2453. Result:=ResBaseTypeNames[bt];
  2454. end;
  2455. procedure TPasResolver.OnFindFirstElement(El: TPasElement; ElScope,
  2456. StartScope: TPasScope; FindFirstElementData: Pointer; var Abort: boolean);
  2457. var
  2458. Data: PPRFindData absolute FindFirstElementData;
  2459. ok: Boolean;
  2460. begin
  2461. ok:=true;
  2462. if (El is TPasProcedure)
  2463. and ProcNeedsParams(TPasProcedure(El).ProcType) then
  2464. // found a proc, but it needs parameters -> remember the first and continue
  2465. ok:=false;
  2466. if ok or (Data^.Found=nil) then
  2467. begin
  2468. Data^.Found:=El;
  2469. Data^.ElScope:=ElScope;
  2470. Data^.StartScope:=StartScope;
  2471. end;
  2472. if ok then
  2473. Abort:=true;
  2474. end;
  2475. procedure TPasResolver.OnFindCallElements(El: TPasElement; ElScope,
  2476. StartScope: TPasScope; FindProcsData: Pointer; var Abort: boolean);
  2477. var
  2478. Data: PFindCallElData absolute FindProcsData;
  2479. Proc, PrevProc: TPasProcedure;
  2480. Distance: integer;
  2481. BuiltInProc: TResElDataBuiltInProc;
  2482. CandidateFound: Boolean;
  2483. VarType, TypeEl: TPasType;
  2484. C: TClass;
  2485. begin
  2486. {$IFDEF VerbosePasResolver}
  2487. writeln('TPasResolver.OnFindCallElements START --------- ',GetObjName(El),' at ',GetElementSourcePosStr(El));
  2488. {$ENDIF}
  2489. CandidateFound:=false;
  2490. if (El is TPasProcedure) then
  2491. begin
  2492. // identifier is a proc
  2493. Proc:=TPasProcedure(El);
  2494. if Data^.Found=Proc then
  2495. begin
  2496. // this proc was already found. This happens when this is the forward
  2497. // declaration or a previously found implementation.
  2498. Data^.ElScope:=ElScope;
  2499. Data^.StartScope:=StartScope;
  2500. exit;
  2501. end;
  2502. if (Proc.CustomData is TPasProcedureScope)
  2503. and (TPasProcedureScope(Proc.CustomData).DeclarationProc<>nil)
  2504. then
  2505. begin
  2506. // this proc has a forward declaration -> use that instead
  2507. Proc:=TPasProcedureScope(Proc.CustomData).DeclarationProc;
  2508. El:=Proc;
  2509. end;
  2510. if Data^.Found is TPasProcedure then
  2511. begin
  2512. // there is already a previous proc
  2513. PrevProc:=TPasProcedure(Data^.Found);
  2514. if (Data^.Distance=cExact) and (PrevProc.Parent<>Proc.Parent)
  2515. and (PrevProc.Parent.ClassType=TPasClassType) then
  2516. begin
  2517. // there was already a perfect proc in a descendant
  2518. Abort:=true;
  2519. exit;
  2520. end;
  2521. // check if previous found proc is override of found proc
  2522. if (PrevProc.IsOverride)
  2523. and (TPasProcedureScope(PrevProc.CustomData).OverriddenProc=Proc) then
  2524. begin
  2525. // previous found proc is override of found proc -> skip
  2526. exit;
  2527. end;
  2528. end;
  2529. Distance:=CheckCallProcCompatibility(Proc.ProcType,Data^.Params,false);
  2530. {$IFDEF VerbosePasResolver}
  2531. writeln('TPasResolver.OnFindCallElements Proc Distance=',Distance,
  2532. ' Data^.Found=',Data^.Found<>nil,' Data^.Distance=',ord(Data^.Distance),
  2533. ' Signature={',GetProcTypeDescription(Proc.ProcType,true,true),'}');
  2534. {$ENDIF}
  2535. CandidateFound:=true;
  2536. end
  2537. else if El is TPasType then
  2538. begin
  2539. TypeEl:=ResolveAliasType(TPasType(El));
  2540. C:=TypeEl.ClassType;
  2541. if C=TPasUnresolvedSymbolRef then
  2542. begin
  2543. if TypeEl.CustomData.ClassType=TResElDataBuiltInProc then
  2544. begin
  2545. // call of built-in proc
  2546. BuiltInProc:=TResElDataBuiltInProc(TypeEl.CustomData);
  2547. if (BuiltInProc.BuiltIn in [bfStrProc,bfStrFunc])
  2548. and ((BuiltInProc.BuiltIn=bfStrProc) = ParentNeedsExprResult(Data^.Params)) then
  2549. begin
  2550. // str function can only be used within an expression
  2551. // str procedure can only be used outside an expression
  2552. {$IFDEF VerbosePasResolver}
  2553. writeln('TPasResolver.OnFindCallElements BuiltInProc=',El.Name,' skip');
  2554. {$ENDIF}
  2555. exit;
  2556. end;
  2557. Distance:=BuiltInProc.GetCallCompatibility(BuiltInProc,Data^.Params,false);
  2558. {$IFDEF VerbosePasResolver}
  2559. writeln('TPasResolver.OnFindCallElements BuiltInProc=',El.Name,' Distance=',Distance);
  2560. {$ENDIF}
  2561. CandidateFound:=true;
  2562. end
  2563. else if TypeEl.CustomData is TResElDataBaseType then
  2564. begin
  2565. // type cast to base type
  2566. Abort:=true; // can't be overloaded
  2567. if Data^.Found<>nil then exit;
  2568. Distance:=CheckTypeCast(TPasType(El),Data^.Params,false);
  2569. {$IFDEF VerbosePasResolver}
  2570. writeln('TPasResolver.OnFindCallElements Base type cast=',El.Name,' Distance=',Distance);
  2571. {$ENDIF}
  2572. CandidateFound:=true;
  2573. end;
  2574. end
  2575. else if (C=TPasClassType)
  2576. or (C=TPasClassOfType)
  2577. or (C=TPasRecordType)
  2578. or (C=TPasEnumType)
  2579. or (C=TPasProcedureType)
  2580. or (C=TPasFunctionType)
  2581. or (C=TPasArrayType) then
  2582. begin
  2583. // type cast to user type
  2584. Abort:=true; // can't be overloaded
  2585. if Data^.Found<>nil then exit;
  2586. Distance:=CheckTypeCast(TPasType(El),Data^.Params,false);
  2587. {$IFDEF VerbosePasResolver}
  2588. writeln('TPasResolver.OnFindCallElements type cast to =',GetObjName(El),' Distance=',Distance);
  2589. {$ENDIF}
  2590. CandidateFound:=true;
  2591. end;
  2592. end
  2593. else if El is TPasVariable then
  2594. begin
  2595. Abort:=true; // can't be overloaded
  2596. if Data^.Found<>nil then exit;
  2597. VarType:=ResolveAliasType(TPasVariable(El).VarType);
  2598. if VarType is TPasProcedureType then
  2599. begin
  2600. Distance:=CheckCallProcCompatibility(TPasProcedureType(VarType),Data^.Params,false);
  2601. {$IFDEF VerbosePasResolver}
  2602. writeln('TPasResolver.OnFindCallElements call var of proctype=',El.Name,' Distance=',Distance);
  2603. {$ENDIF}
  2604. CandidateFound:=true;
  2605. end;
  2606. end
  2607. else if El.ClassType=TPasArgument then
  2608. begin
  2609. Abort:=true; // can't be overloaded
  2610. if Data^.Found<>nil then exit;
  2611. VarType:=ResolveAliasType(TPasArgument(El).ArgType);
  2612. if VarType is TPasProcedureType then
  2613. begin
  2614. Distance:=CheckCallProcCompatibility(TPasProcedureType(VarType),Data^.Params,false);
  2615. {$IFDEF VerbosePasResolver}
  2616. writeln('TPasResolver.OnFindCallElements call arg of proctype=',El.Name,' Distance=',Distance);
  2617. {$ENDIF}
  2618. CandidateFound:=true;
  2619. end;
  2620. end;
  2621. if not CandidateFound then
  2622. begin
  2623. // El does not support the () operator
  2624. Abort:=true;
  2625. if Data^.Found=nil then
  2626. begin
  2627. // El is the first element found -> raise error
  2628. // ToDo: use the ( as error position
  2629. RaiseMsg(20170216151525,nIllegalQualifier,sIllegalQualifier,['('],Data^.Params);
  2630. end;
  2631. exit;
  2632. end;
  2633. // El is a candidate (might be incompatible)
  2634. if (Data^.Found=nil)
  2635. or ((Data^.Distance=cIncompatible) and (Distance<cIncompatible)) then
  2636. begin
  2637. {$IFDEF VerbosePasResolver}
  2638. writeln('TPasResolver.OnFindCallElements Found first candidate Distance=',Distance);
  2639. {$ENDIF}
  2640. Data^.Found:=El;
  2641. Data^.ElScope:=ElScope;
  2642. Data^.StartScope:=StartScope;
  2643. Data^.Distance:=Distance;
  2644. Data^.Count:=1;
  2645. if Data^.List<>nil then
  2646. begin
  2647. Data^.List.Clear;
  2648. Data^.List.Add(El);
  2649. end;
  2650. end
  2651. else if Distance=cIncompatible then
  2652. // another candidate, but it is incompatible -> ignore
  2653. {$IFDEF VerbosePasResolver}
  2654. writeln('TPasResolver.OnFindCallElements Found another candidate, but it is incompatible -> ignore')
  2655. {$ENDIF}
  2656. else if (Distance>=cCompatibleWithDefaultParams)
  2657. or (Data^.Distance=Distance)
  2658. or ((Distance>=cLossyConversion) and (Data^.Distance>=cLossyConversion)) then
  2659. begin
  2660. // found another compatible one -> collect
  2661. {$IFDEF VerbosePasResolver}
  2662. writeln('TPasResolver.OnFindCallElements Found another candidate Distance=',Distance,' OldDistance=',Data^.Distance);
  2663. {$ENDIF}
  2664. inc(Data^.Count);
  2665. if (Data^.List<>nil) then
  2666. begin
  2667. if (Data^.List.IndexOf(El)>=0) then
  2668. begin
  2669. {$IFDEF VerbosePasResolver}
  2670. writeln('TPasResolver.OnFindCallElements Found El twice: ',GetTreeDbg(El),
  2671. ' ',GetElementSourcePosStr(El),
  2672. ' PrevElScope=',GetObjName(Data^.ElScope),' ',GetTreeDbg(Data^.ElScope.Element),
  2673. ' ElScope=',GetObjName(ElScope),' ',GetTreeDbg(ElScope.Element)
  2674. );
  2675. {$ENDIF}
  2676. RaiseInternalError(20160924230805);
  2677. end;
  2678. Data^.List.Add(El);
  2679. end;
  2680. end
  2681. else if (Distance<Data^.Distance) then
  2682. begin
  2683. // found a better one
  2684. {$IFDEF VerbosePasResolver}
  2685. writeln('TPasResolver.OnFindCallElements Found a better candidate Distance=',Distance,' Data^.Distance=',Data^.Distance);
  2686. {$ENDIF}
  2687. Data^.Found:=El;
  2688. Data^.ElScope:=ElScope;
  2689. Data^.StartScope:=StartScope;
  2690. Data^.Distance:=Distance;
  2691. if (Distance<cLossyConversion) then
  2692. begin
  2693. // found a good one
  2694. Data^.Count:=1;
  2695. if Data^.List<>nil then
  2696. Data^.List.Clear;
  2697. end
  2698. else
  2699. begin
  2700. // found another lossy one
  2701. // -> collect them
  2702. inc(Data^.Count);
  2703. end;
  2704. if Data^.List<>nil then
  2705. Data^.List.Add(El);
  2706. end;
  2707. end;
  2708. procedure TPasResolver.OnFindOverloadProc(El: TPasElement; ElScope,
  2709. StartScope: TPasScope; FindOverloadData: Pointer; var Abort: boolean);
  2710. var
  2711. Data: PFindOverloadProcData absolute FindOverloadData;
  2712. Proc: TPasProcedure;
  2713. begin
  2714. //writeln('TPasResolver.OnFindOverloadProc START ',El.Name,':',El.ElementTypeName,' itself=',El=Data^.Proc);
  2715. if not (El is TPasProcedure) then
  2716. begin
  2717. // identifier is not a proc
  2718. if (El is TPasVariable) then
  2719. begin
  2720. if TPasVariable(El).Visibility=visStrictPrivate then
  2721. exit;
  2722. if (TPasVariable(El).Visibility=visPrivate)
  2723. and (El.GetModule<>StartScope.Element.GetModule) then
  2724. exit;
  2725. end;
  2726. Data^.FoundNonProc:=El;
  2727. Abort:=true;
  2728. exit;
  2729. end;
  2730. // identifier is a proc
  2731. if El=Data^.Proc then
  2732. exit; // found itself -> normal when searching for overloads
  2733. //writeln('TPasResolver.OnFindOverloadProc Data^.OnlyScope=',GetObjName(Data^.OnlyScope),' ElScope=',GetObjName(ElScope),' ',Data^.OnlyScope=ElScope);
  2734. if (Data^.OnlyScope<>nil) and (Data^.OnlyScope<>ElScope) then
  2735. begin
  2736. // do not search any further, only one scope should be searched
  2737. // for example when searching the method declaration of a method body
  2738. Abort:=false;
  2739. exit;
  2740. end;
  2741. {$IFDEF VerbosePasResolver}
  2742. writeln('TPasResolver.OnFindOverloadProc ',GetTreeDbg(El,2));
  2743. {$ENDIF}
  2744. Proc:=TPasProcedure(El);
  2745. if CheckOverloadProcCompatibility(Data^.Proc,Proc) then
  2746. begin
  2747. Data^.Found:=Proc;
  2748. Data^.ElScope:=ElScope;
  2749. Data^.StartScope:=StartScope;
  2750. Abort:=true;
  2751. end;
  2752. end;
  2753. procedure TPasResolver.SetCurrentParser(AValue: TPasParser);
  2754. begin
  2755. //writeln('TPasResolver.SetCurrentParser ',AValue<>nil);
  2756. if AValue=CurrentParser then exit;
  2757. Clear;
  2758. inherited SetCurrentParser(AValue);
  2759. if CurrentParser<>nil then
  2760. CurrentParser.Options:=CurrentParser.Options
  2761. +[po_resolvestandardtypes,po_nooverloadedprocs,po_keepclassforward,
  2762. po_arrayrangeexpr,po_CheckModeswitches,po_CheckCondFunction];
  2763. end;
  2764. procedure TPasResolver.CheckTopScope(ExpectedClass: TPasScopeClass);
  2765. begin
  2766. if TopScope=nil then
  2767. RaiseInternalError(20160922163319,'Expected TopScope='+ExpectedClass.ClassName+' but found nil');
  2768. if TopScope.ClassType<>ExpectedClass then
  2769. RaiseInternalError(20160922163323,'Expected TopScope='+ExpectedClass.ClassName+' but found '+TopScope.ClassName);
  2770. end;
  2771. function TPasResolver.AddIdentifier(Scope: TPasIdentifierScope;
  2772. const aName: String; El: TPasElement; const Kind: TPasIdentifierKind
  2773. ): TPasIdentifier;
  2774. var
  2775. Identifier, OlderIdentifier: TPasIdentifier;
  2776. ClassScope: TPasClassScope;
  2777. OlderEl: TPasElement;
  2778. IsClassScope: Boolean;
  2779. C: TClass;
  2780. begin
  2781. IsClassScope:=(Scope is TPasClassScope);
  2782. if (El.Visibility=visPublished) then
  2783. begin
  2784. C:=El.ClassType;
  2785. if (C=TPasProperty) or (C=TPasVariable) then
  2786. // Note: VarModifiers are not yet set
  2787. else if (C=TPasProcedure) or (C=TPasFunction) then
  2788. // ok
  2789. else
  2790. RaiseMsg(20170403223024,nSymbolCannotBePublished,sSymbolCannotBePublished,[],El);
  2791. end;
  2792. if (Kind=pikSimple) and IsClassScope
  2793. and (El.ClassType<>TPasProperty) then
  2794. begin
  2795. // check duplicate in ancestors
  2796. ClassScope:=TPasClassScope(Scope).AncestorScope;
  2797. while ClassScope<>nil do
  2798. begin
  2799. OlderIdentifier:=ClassScope.FindLocalIdentifier(aName);
  2800. while OlderIdentifier<>nil do
  2801. begin
  2802. OlderEl:=OlderIdentifier.Element;
  2803. OlderIdentifier:=OlderIdentifier.NextSameIdentifier;
  2804. if OlderEl is TPasVariable then
  2805. begin
  2806. if TPasVariable(OlderEl).Visibility=visStrictPrivate then
  2807. continue; // OlderEl is hidden
  2808. if (TPasVariable(OlderEl).Visibility=visPrivate)
  2809. and (OlderEl.GetModule<>El.GetModule) then
  2810. continue; // OlderEl is hidden
  2811. end;
  2812. RaiseMsg(20170221130001,nDuplicateIdentifier,sDuplicateIdentifier,
  2813. [aName,GetElementSourcePosStr(OlderEl)],El);
  2814. end;
  2815. ClassScope:=ClassScope.AncestorScope;
  2816. end;
  2817. end;
  2818. Identifier:=Scope.AddIdentifier(aName,El,Kind);
  2819. // check duplicate in current scope
  2820. OlderIdentifier:=Identifier.NextSameIdentifier;
  2821. if (OlderIdentifier<>nil) then
  2822. if (Identifier.Kind=pikSimple)
  2823. or (OlderIdentifier.Kind=pikSimple)
  2824. or (El.Visibility=visPublished) then
  2825. begin
  2826. if (OlderIdentifier.Element.ClassType=TPasEnumValue)
  2827. and (OlderIdentifier.Element.Parent.Parent<>Scope.Element) then
  2828. // this enum was propagated from a sub type -> remove enum
  2829. Scope.RemoveLocalIdentifier(OlderIdentifier.Element);
  2830. RaiseMsg(20170216151530,nDuplicateIdentifier,sDuplicateIdentifier,
  2831. [aName,GetElementSourcePosStr(OlderIdentifier.Element)],El);
  2832. end;
  2833. Result:=Identifier;
  2834. end;
  2835. procedure TPasResolver.FinishModule(CurModule: TPasModule);
  2836. var
  2837. CurModuleClass: TClass;
  2838. i: Integer;
  2839. begin
  2840. {$IFDEF VerbosePasResolver}
  2841. writeln('TPasResolver.FinishModule START ',CurModule.Name);
  2842. {$ENDIF}
  2843. CurModuleClass:=CurModule.ClassType;
  2844. if (CurModuleClass=TPasProgram) or (CurModuleClass=TPasLibrary) then
  2845. begin
  2846. // resolve begin..end block
  2847. ResolveImplBlock(CurModule.InitializationSection);
  2848. end
  2849. else if (CurModuleClass=TPasModule) then
  2850. begin
  2851. if CurModule.FinalizationSection<>nil then
  2852. // finalization section finished -> resolve
  2853. ResolveImplBlock(CurModule.FinalizationSection);
  2854. if CurModule.InitializationSection<>nil then
  2855. // initialization section finished -> resolve
  2856. ResolveImplBlock(CurModule.InitializationSection);
  2857. end
  2858. else
  2859. RaiseInternalError(20160922163327); // unknown module
  2860. // check all methods have bodies
  2861. // and all forward classes and pointers are resolved
  2862. for i:=0 to FPendingForwards.Count-1 do
  2863. CheckPendingForwards(TPasElement(FPendingForwards[i]));
  2864. FPendingForwards.Clear;
  2865. // close all sections
  2866. while (TopScope<>nil) and (TopScope.ClassType=TPasSectionScope) do
  2867. PopScope;
  2868. CheckTopScope(TPasModuleScope);
  2869. PopScope;
  2870. {$IFDEF VerbosePasResolver}
  2871. writeln('TPasResolver.FinishModule END ',CurModule.Name);
  2872. {$ENDIF}
  2873. end;
  2874. procedure TPasResolver.FinishUsesClause;
  2875. var
  2876. Section, CurSection: TPasSection;
  2877. i, j: Integer;
  2878. PublicEl, UseModule: TPasElement;
  2879. Scope: TPasSectionScope;
  2880. UsesScope: TPasIdentifierScope;
  2881. UseUnit: TPasUsesUnit;
  2882. FirstName: String;
  2883. p: SizeInt;
  2884. OldIdentifier: TPasIdentifier;
  2885. begin
  2886. CheckTopScope(TPasSectionScope);
  2887. Scope:=TPasSectionScope(TopScope);
  2888. Section:=TPasSection(Scope.Element);
  2889. {$IFDEF VerbosePasResolver}
  2890. writeln('TPasResolver.FinishUsesClause Section=',Section.ClassName,' Section.UsesList.Count=',Section.UsesList.Count);
  2891. {$ENDIF}
  2892. for i:=0 to Section.UsesList.Count-1 do
  2893. begin
  2894. UseUnit:=Section.UsesClause[i];
  2895. {$IFDEF VerbosePasResolver}
  2896. writeln('TPasResolver.FinishUsesClause ',GetObjName(UseUnit));
  2897. {$ENDIF}
  2898. UseModule:=UseUnit.Module;
  2899. // check used unit
  2900. PublicEl:=nil;
  2901. if (UseModule.ClassType=TLibrarySection) then
  2902. PublicEl:=UseModule
  2903. else if (UseModule.ClassType=TPasModule) then
  2904. PublicEl:=TPasModule(UseModule).InterfaceSection
  2905. else
  2906. RaiseXExpectedButYFound(20170503004803,'unit',UseModule.ElementTypeName,UseUnit);
  2907. if PublicEl=nil then
  2908. RaiseInternalError(20160922163352,'uses element has no interface section: '+GetObjName(UseModule));
  2909. if PublicEl.CustomData=nil then
  2910. RaiseInternalError(20160922163358,'uses element has no resolver data: '
  2911. +UseUnit.Name+'->'+GetObjName(PublicEl));
  2912. if not (PublicEl.CustomData is TPasIdentifierScope) then
  2913. RaiseInternalError(20160922163403,'uses element has invalid resolver data: '
  2914. +UseUnit.Name+'->'+GetObjName(PublicEl)+'->'+PublicEl.CustomData.ClassName);
  2915. // check if module was already used by a different name
  2916. j:=i;
  2917. CurSection:=Section;
  2918. repeat
  2919. dec(j);
  2920. if j<0 then
  2921. begin
  2922. if CurSection.ClassType<>TImplementationSection then
  2923. break;
  2924. CurSection:=CurSection.GetModule.InterfaceSection;
  2925. if CurSection=nil then break;
  2926. j:=length(CurSection.UsesClause)-1;
  2927. if j<0 then break;
  2928. end;
  2929. if CurSection.UsesClause[j].Module=UseModule then
  2930. RaiseMsg(20170503004022,nDuplicateIdentifier,sDuplicateIdentifier,
  2931. [UseModule.Name,GetElementSourcePosStr(CurSection.UsesClause[j])],UseUnit);
  2932. until false;
  2933. // add full uses name
  2934. AddIdentifier(Scope,UseUnit.Name,UseUnit,pikSimple);
  2935. // add scope
  2936. UsesScope:=TPasIdentifierScope(PublicEl.CustomData);
  2937. {$IFDEF VerbosePasResolver}
  2938. writeln('TPasResolver.FinishUsesClause Add UsesScope=',GetObjName(UsesScope));
  2939. {$ENDIF}
  2940. Scope.UsesScopes.Add(UsesScope);
  2941. EmitElementHints(Section,UseUnit);
  2942. end;
  2943. // Note: a sub identifier (e.g. a class member) hides all unitnames starting
  2944. // with this identifier
  2945. // -> add first name of dotted unitname as identifier
  2946. for i:=0 to Section.UsesList.Count-1 do
  2947. begin
  2948. UseUnit:=Section.UsesClause[i];
  2949. FirstName:=UseUnit.Name;
  2950. p:=Pos('.',FirstName);
  2951. if p<1 then continue;
  2952. FirstName:=LeftStr(FirstName,p-1);
  2953. OldIdentifier:=Scope.FindLocalIdentifier(FirstName);
  2954. if OldIdentifier=nil then
  2955. AddIdentifier(Scope,FirstName,UseUnit.Module,pikSimple)
  2956. else
  2957. // a reference in the implementation needs to find a match in the
  2958. // implementation clause -> replace identfier in the scope
  2959. OldIdentifier.Element:=UseUnit;
  2960. end;
  2961. end;
  2962. procedure TPasResolver.FinishTypeSection(El: TPasDeclarations);
  2963. var
  2964. i: Integer;
  2965. Decl: TPasElement;
  2966. ClassOfEl: TPasClassOfType;
  2967. Data: TPRFindData;
  2968. UnresolvedEl: TUnresolvedPendingRef;
  2969. Abort: boolean;
  2970. OldClassType: TPasClassType;
  2971. ClassOfName: String;
  2972. begin
  2973. // resolve pending forwards
  2974. for i:=0 to El.Declarations.Count-1 do
  2975. begin
  2976. Decl:=TPasElement(El.Declarations[i]);
  2977. if Decl is TPasClassType then
  2978. begin
  2979. if TPasClassType(Decl).IsForward and (TPasClassType(Decl).CustomData=nil) then
  2980. RaiseMsg(20170216151534,nForwardTypeNotResolved,sForwardTypeNotResolved,[Decl.Name],Decl);
  2981. end
  2982. else if (Decl.ClassType=TPasClassOfType) then
  2983. begin
  2984. ClassOfEl:=TPasClassOfType(Decl);
  2985. Data:=Default(TPRFindData);
  2986. if (ClassOfEl.DestType.ClassType=TUnresolvedPendingRef) then
  2987. begin
  2988. // forward class-of -> resolve now
  2989. UnresolvedEl:=TUnresolvedPendingRef(ClassOfEl.DestType);
  2990. ClassOfName:=UnresolvedEl.Name;
  2991. {$IFDEF VerbosePasResolver}
  2992. writeln('TPasResolver.FinishTypeSection resolving "',ClassOfEl.Name,'" = class of unresolved "',ClassOfName,'"');
  2993. {$ENDIF}
  2994. Data.ErrorPosEl:=UnresolvedEl;
  2995. Abort:=false;
  2996. (TopScope as TPasIdentifierScope).IterateElements(ClassOfName,
  2997. TopScope,@OnFindFirstElement,@Data,Abort);
  2998. if (Data.Found=nil) then
  2999. RaiseIdentifierNotFound(20170216151543,UnresolvedEl.Name,UnresolvedEl);
  3000. if Data.Found.ClassType<>TPasClassType then
  3001. RaiseXExpectedButYFound(20170216151548,'class',Data.Found.ElementTypeName,UnresolvedEl);
  3002. // replace unresolved
  3003. ClassOfEl.DestType:=TPasClassType(Data.Found);
  3004. ClassOfEl.DestType.AddRef;
  3005. UnresolvedEl.Release;
  3006. end
  3007. else
  3008. begin
  3009. // class-of has found a type
  3010. // another later in the same type section has priority -> check
  3011. OldClassType:=ClassOfEl.DestType as TPasClassType;
  3012. if ClassOfEl.DestType.Parent=ClassOfEl.Parent then
  3013. continue; // class in same type section -> ok
  3014. // class not in same type section -> check
  3015. ClassOfName:=OldClassType.Name;
  3016. {$IFDEF VerbosePasResolver}
  3017. writeln('TPasResolver.FinishTypeSection resolving "',ClassOfEl.Name,'" = class of resolved "',ClassOfName,'"');
  3018. {$ENDIF}
  3019. Data.ErrorPosEl:=ClassOfEl;
  3020. Abort:=false;
  3021. (TopScope as TPasIdentifierScope).IterateElements(ClassOfName,
  3022. TopScope,@OnFindFirstElement,@Data,Abort);
  3023. if (Data.Found=nil) then
  3024. continue;
  3025. if Data.Found.ClassType<>TPasClassType then
  3026. RaiseXExpectedButYFound(20170221171040,'class',Data.Found.ElementTypeName,ClassOfEl);
  3027. ClassOfEl.DestType:=TPasClassType(Data.Found);
  3028. ClassOfEl.DestType.AddRef;
  3029. OldClassType.Release;
  3030. end;
  3031. end;
  3032. end;
  3033. end;
  3034. procedure TPasResolver.FinishTypeDef(El: TPasType);
  3035. var
  3036. C: TClass;
  3037. begin
  3038. {$IFDEF VerbosePasResolver}
  3039. writeln('TPasResolver.FinishTypeDef El=',GetObjName(El));
  3040. {$ENDIF}
  3041. C:=El.ClassType;
  3042. if C=TPasEnumType then
  3043. FinishEnumType(TPasEnumType(El))
  3044. else if C=TPasSetType then
  3045. FinishSetType(TPasSetType(El))
  3046. else if C=TPasRangeType then
  3047. FinishRangeType(TPasRangeType(El))
  3048. else if C=TPasRecordType then
  3049. FinishRecordType(TPasRecordType(El))
  3050. else if C=TPasClassType then
  3051. FinishClassType(TPasClassType(El))
  3052. else if C=TPasClassOfType then
  3053. FinishClassOfType(TPasClassOfType(El))
  3054. else if C=TPasArrayType then
  3055. FinishArrayType(TPasArrayType(El));
  3056. end;
  3057. procedure TPasResolver.FinishEnumType(El: TPasEnumType);
  3058. begin
  3059. if TopScope.Element=El then
  3060. PopScope;
  3061. end;
  3062. procedure TPasResolver.FinishSetType(El: TPasSetType);
  3063. var
  3064. BaseTypeData: TResElDataBaseType;
  3065. StartResolved, EndResolved: TPasResolverResult;
  3066. RangeExpr: TBinaryExpr;
  3067. C: TClass;
  3068. EnumType: TPasType;
  3069. begin
  3070. EnumType:=El.EnumType;
  3071. C:=EnumType.ClassType;
  3072. if C=TPasEnumType then
  3073. begin
  3074. FinishSubElementType(El,EnumType);
  3075. exit;
  3076. end
  3077. else if C=TPasRangeType then
  3078. begin
  3079. RangeExpr:=TPasRangeType(EnumType).RangeExpr;
  3080. if RangeExpr.Parent=El then
  3081. FinishConstRangeExpr(RangeExpr.left,RangeExpr.right,StartResolved,EndResolved);
  3082. FinishSubElementType(El,EnumType);
  3083. exit;
  3084. end
  3085. else if C=TPasUnresolvedSymbolRef then
  3086. begin
  3087. if EnumType.CustomData is TResElDataBaseType then
  3088. begin
  3089. BaseTypeData:=TResElDataBaseType(EnumType.CustomData);
  3090. if BaseTypeData.BaseType in (btAllChars+[btBoolean]) then
  3091. exit;
  3092. RaiseXExpectedButYFound(20170216151553,'char or boolean',EnumType.ElementTypeName,EnumType);
  3093. end;
  3094. end;
  3095. RaiseXExpectedButYFound(20170216151557,'enum type',EnumType.ElementTypeName,EnumType);
  3096. end;
  3097. procedure TPasResolver.FinishSubElementType(Parent: TPasElement; El: TPasType);
  3098. var
  3099. Decl: TPasDeclarations;
  3100. EnumScope: TPasEnumTypeScope;
  3101. begin
  3102. EmitTypeHints(Parent,El);
  3103. if (El.Name<>'') or (AnonymousElTypePostfix='') then exit;
  3104. if Parent.Name='' then
  3105. RaiseMsg(20170415165455,nCannotNestAnonymousX,sCannotNestAnonymousX,[El.ElementTypeName],El);
  3106. if not (Parent.Parent is TPasDeclarations) then
  3107. RaiseMsg(20170416094735,nCannotNestAnonymousX,sCannotNestAnonymousX,[El.ElementTypeName],El);
  3108. // give anonymous sub type a name
  3109. El.Name:=Parent.Name+AnonymousElTypePostfix;
  3110. {$IFDEF VerbosePasResolver}
  3111. writeln('TPasResolver.FinishSubElementType parent="',GetObjName(Parent),'" named anonymous type "',GetObjName(El),'"');
  3112. {$ENDIF}
  3113. Decl:=TPasDeclarations(Parent.Parent);
  3114. Decl.Declarations.Add(El);
  3115. El.AddRef;
  3116. El.Parent:=Decl;
  3117. Decl.Types.Add(El);
  3118. if (El.ClassType=TPasEnumType) and (Parent.ClassType=TPasSetType) then
  3119. begin
  3120. EnumScope:=TPasEnumTypeScope(El.CustomData);
  3121. if EnumScope.CanonicalSet<>Parent then
  3122. begin
  3123. if EnumScope.CanonicalSet<>nil then
  3124. EnumScope.CanonicalSet.Release;
  3125. EnumScope.CanonicalSet:=TPasSetType(Parent);
  3126. Parent.AddRef;
  3127. end;
  3128. end;
  3129. end;
  3130. procedure TPasResolver.FinishRangeType(El: TPasRangeType);
  3131. var
  3132. StartResolved, EndResolved: TPasResolverResult;
  3133. begin
  3134. ResolveExpr(El.RangeExpr.left,rraRead);
  3135. ResolveExpr(El.RangeExpr.right,rraRead);
  3136. FinishConstRangeExpr(El.RangeExpr.left,El.RangeExpr.right,StartResolved,EndResolved);
  3137. end;
  3138. procedure TPasResolver.FinishConstRangeExpr(Left, Right: TPasExpr; out LeftResolved,
  3139. RightResolved: TPasResolverResult);
  3140. // for example Left..Right
  3141. var
  3142. RgValue: TResEvalValue;
  3143. begin
  3144. {$IFDEF VerbosePasResEval}
  3145. writeln('TPasResolver.FinishConstRangeExpr Left=',GetObjName(Left),' Right=',GetObjName(Right));
  3146. {$ENDIF}
  3147. // check type compatibility
  3148. ComputeElement(Left,LeftResolved,[rcSkipTypeAlias,rcConstant]);
  3149. ComputeElement(Right,RightResolved,[rcSkipTypeAlias,rcConstant]);
  3150. CheckSetLitElCompatible(Left,Right,LeftResolved,RightResolved);
  3151. RgValue:=Eval(Left.Parent as TBinaryExpr,[refConst]);
  3152. ReleaseEvalValue(RgValue);
  3153. end;
  3154. procedure TPasResolver.FinishRecordType(El: TPasRecordType);
  3155. begin
  3156. if TopScope.Element=El then
  3157. PopScope;
  3158. end;
  3159. procedure TPasResolver.FinishClassType(El: TPasClassType);
  3160. begin
  3161. if TopScope.Element=El then
  3162. PopScope;
  3163. end;
  3164. procedure TPasResolver.FinishClassOfType(El: TPasClassOfType);
  3165. begin
  3166. if El.DestType is TUnresolvedPendingRef then exit;
  3167. if El.DestType is TPasClassType then exit;
  3168. RaiseMsg(20170216151602,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  3169. [El.DestType.Name,'class'],El);
  3170. end;
  3171. procedure TPasResolver.FinishArrayType(El: TPasArrayType);
  3172. var
  3173. i: Integer;
  3174. Expr: TPasExpr;
  3175. RangeResolved: TPasResolverResult;
  3176. begin
  3177. for i:=0 to length(El.Ranges)-1 do
  3178. begin
  3179. Expr:=El.Ranges[i];
  3180. ResolveExpr(Expr,rraRead);
  3181. ComputeElement(Expr,RangeResolved,[rcConstant]);
  3182. if (RangeResolved.IdentEl<>nil) and not (RangeResolved.IdentEl is TPasType) then
  3183. RaiseXExpectedButYFound(20170216151607,'range',RangeResolved.IdentEl.ElementTypeName,Expr);
  3184. if (RangeResolved.BaseType=btRange) and (RangeResolved.SubType in btArrayRangeTypes) then
  3185. // range, e.g. 1..2
  3186. else if RangeResolved.BaseType in btArrayRangeTypes then
  3187. // full range, e.g. array[char]
  3188. else if (RangeResolved.BaseType=btContext) and (RangeResolved.TypeEl is TPasEnumType) then
  3189. // e.g. array[enumtype]
  3190. else
  3191. RaiseXExpectedButYFound(20170216151609,'range',RangeResolved.IdentEl.ElementTypeName,Expr);
  3192. end;
  3193. FinishSubElementType(El,El.ElType);
  3194. end;
  3195. procedure TPasResolver.FinishConstDef(El: TPasConst);
  3196. begin
  3197. ResolveExpr(El.Expr,rraRead);
  3198. if El.VarType<>nil then
  3199. CheckAssignCompatibility(El,El.Expr,true)
  3200. else
  3201. Eval(El.Expr,[refConst])
  3202. end;
  3203. procedure TPasResolver.FinishProcedure(aProc: TPasProcedure);
  3204. var
  3205. i: Integer;
  3206. Body: TProcedureBody;
  3207. SubEl: TPasElement;
  3208. SubProcScope: TPasProcedureScope;
  3209. begin
  3210. {$IFDEF VerbosePasResolver}
  3211. writeln('TPasResolver.FinishProcedure START');
  3212. {$ENDIF}
  3213. CheckTopScope(TPasProcedureScope);
  3214. if TPasProcedureScope(TopScope).Element<>aProc then
  3215. RaiseInternalError(20170220163043);
  3216. Body:=aProc.Body;
  3217. if Body<>nil then
  3218. begin
  3219. if Body.Body is TPasImplAsmStatement then
  3220. aProc.Modifiers:=aProc.Modifiers+[pmAssembler];
  3221. ResolveImplBlock(Body.Body);
  3222. // check if all forward procs are resolved
  3223. for i:=0 to Body.Declarations.Count-1 do
  3224. begin
  3225. SubEl:=TPasElement(Body.Declarations[i]);
  3226. if (SubEl is TPasProcedure) and TPasProcedure(SubEl).IsForward then
  3227. begin
  3228. SubProcScope:=TPasProcedure(SubEl).CustomData as TPasProcedureScope;
  3229. if SubProcScope.ImplProc=nil then
  3230. RaiseMsg(20170216151613,nForwardProcNotResolved,sForwardProcNotResolved,
  3231. [SubEl.ElementTypeName,SubEl.Name],SubEl);
  3232. end;
  3233. end;
  3234. end;
  3235. PopScope;
  3236. end;
  3237. procedure TPasResolver.FinishProcedureType(El: TPasProcedureType);
  3238. var
  3239. ProcName: String;
  3240. FindData: TFindOverloadProcData;
  3241. DeclProc, Proc, ParentProc: TPasProcedure;
  3242. Abort, HasDots: boolean;
  3243. DeclProcScope, ProcScope: TPasProcedureScope;
  3244. ParentScope: TPasScope;
  3245. pm: TProcedureModifier;
  3246. ptm: TProcTypeModifier;
  3247. begin
  3248. if (El.Parent is TPasProcedure) and (TPasProcedure(El.Parent).ProcType=El) then
  3249. begin
  3250. // finished header of a procedure declaration
  3251. // -> search the best fitting proc
  3252. CheckTopScope(TPasProcedureScope);
  3253. Proc:=TPasProcedure(El.Parent);
  3254. {$IFDEF VerbosePasResolver}
  3255. writeln('TPasResolver.FinishProcedureHeader El=',GetTreeDbg(El),' ',GetElementSourcePosStr(El),' IsForward=',Proc.IsForward,' Parent=',GetObjName(El.Parent));
  3256. {$ENDIF}
  3257. ProcName:=Proc.Name;
  3258. if (proProcTypeWithoutIsNested in Options) and El.IsNested then
  3259. RaiseInvalidProcTypeModifier(20170402120811,El,ptmIsNested,El);
  3260. if (Proc.Parent.ClassType=TProcedureBody) then
  3261. begin
  3262. // nested sub proc
  3263. if not (proProcTypeWithoutIsNested in Options) then
  3264. El.IsNested:=true;
  3265. // inherit 'of Object'
  3266. ParentProc:=Proc.Parent.Parent as TPasProcedure;
  3267. if ParentProc.ProcType.IsOfObject then
  3268. El.IsOfObject:=true;
  3269. end;
  3270. if El.IsReferenceTo then
  3271. begin
  3272. if El.IsNested then
  3273. RaiseInvalidProcTypeModifier(20170419142818,El,ptmIsNested,El);
  3274. if El.IsOfObject then
  3275. RaiseInvalidProcTypeModifier(20170419142844,El,ptmOfObject,El);
  3276. end;
  3277. if Proc.IsExternal then
  3278. begin
  3279. for pm in TProcedureModifier do
  3280. if (pm in Proc.Modifiers)
  3281. and not (pm in [pmVirtual, pmDynamic, pmOverride,
  3282. pmOverload, pmMessage, pmReintroduce,
  3283. pmExternal, pmDispId,
  3284. pmfar]) then
  3285. RaiseMsg(20170216151616,nInvalidXModifierY,
  3286. sInvalidXModifierY,[Proc.ElementTypeName,'external, '+ModifierNames[pm]],Proc);
  3287. for ptm in TProcTypeModifier do
  3288. if (ptm in Proc.ProcType.Modifiers)
  3289. and not (ptm in [ptmOfObject,ptmIsNested,ptmStatic,ptmVarargs,ptmReferenceTo]) then
  3290. RaiseMsg(20170411171224,nInvalidXModifierY,
  3291. sInvalidXModifierY,[Proc.ElementTypeName,'external, '+ProcTypeModifiers[ptm]],Proc);
  3292. end;
  3293. HasDots:=Pos('.',ProcName)>1;
  3294. if Proc.Parent is TPasClassType then
  3295. begin
  3296. // method declaration
  3297. if Proc.IsAbstract then
  3298. begin
  3299. if not Proc.IsVirtual then
  3300. RaiseMsg(20170216151623,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'abstract without virtual'],Proc);
  3301. if Proc.IsOverride then
  3302. RaiseMsg(20170216151625,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'abstract, override'],Proc);
  3303. end;
  3304. if Proc.IsVirtual and Proc.IsOverride then
  3305. RaiseMsg(20170216151627,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'virtual, override'],Proc);
  3306. if Proc.IsForward then
  3307. RaiseMsg(20170216151629,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'forward'],Proc);
  3308. if Proc.IsStatic then
  3309. if (Proc.ClassType<>TPasClassProcedure) and (Proc.ClassType<>TPasClassFunction) then
  3310. RaiseMsg(20170216151631,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,'static'],Proc);
  3311. end
  3312. else
  3313. begin
  3314. // intf proc, forward proc, proc body, method body
  3315. if Proc.IsAbstract then
  3316. RaiseInvalidProcModifier(20170216151634,Proc,pmAbstract,Proc);
  3317. if Proc.IsVirtual then
  3318. RaiseInvalidProcModifier(20170216151635,Proc,pmVirtual,Proc);
  3319. if Proc.IsOverride then
  3320. RaiseInvalidProcModifier(20170216151637,Proc,pmOverride,Proc);
  3321. if Proc.IsMessage then
  3322. RaiseInvalidProcModifier(20170216151638,Proc,pmMessage,Proc);
  3323. if Proc.IsStatic then
  3324. RaiseInvalidProcTypeModifier(20170216151640,El,ptmStatic,El);
  3325. if (not HasDots)
  3326. and (Proc.ClassType<>TPasProcedure)
  3327. and (Proc.ClassType<>TPasFunction) then
  3328. RaiseMsg(20170419232724,nXExpectedButYFound,sXExpectedButYFound,
  3329. ['full method name','short name'],El);
  3330. end;
  3331. if HasDots then
  3332. begin
  3333. FinishMethodImplHeader(Proc);
  3334. exit;
  3335. end;
  3336. // finish interface/implementation/nested procedure/method declaration
  3337. if not IsValidIdent(ProcName) then
  3338. RaiseNotYetImplemented(20160922163407,El);
  3339. if Proc.LibraryExpr<>nil then
  3340. ResolveExpr(Proc.LibraryExpr,rraRead);
  3341. if Proc.LibrarySymbolName<>nil then
  3342. ResolveExpr(Proc.LibrarySymbolName,rraRead);
  3343. if Proc.Parent is TPasClassType then
  3344. begin
  3345. FinishMethodDeclHeader(Proc);
  3346. exit;
  3347. end;
  3348. // finish interface/implementation/nested procedure
  3349. FindData:=Default(TFindOverloadProcData);
  3350. FindData.Proc:=Proc;
  3351. FindData.Args:=Proc.ProcType.Args;
  3352. Abort:=false;
  3353. IterateElements(ProcName,@OnFindOverloadProc,@FindData,Abort);
  3354. if FindData.FoundNonProc<>nil then
  3355. begin
  3356. // proc hides a non proc -> forbidden within module
  3357. if (Proc.GetModule=FindData.FoundNonProc.GetModule) then
  3358. RaiseMsg(20170216151649,nDuplicateIdentifier,sDuplicateIdentifier,
  3359. [FindData.FoundNonProc.Name,GetElementSourcePosStr(FindData.FoundNonProc)],Proc.ProcType);
  3360. end;
  3361. if FindData.Found=nil then
  3362. exit; // no overload -> ok
  3363. // overload found with same signature
  3364. DeclProc:=FindData.Found;
  3365. {$IFDEF VerbosePasResolver}
  3366. writeln('TPasResolver.FinishProcedureHeader overload found: Proc2=',GetTreeDbg(DeclProc),' ',GetElementSourcePosStr(DeclProc),' IsForward=',DeclProc.IsForward,' Parent=',GetObjName(DeclProc.Parent));
  3367. {$ENDIF}
  3368. if (Proc.Parent=DeclProc.Parent)
  3369. or ((Proc.Parent is TImplementationSection)
  3370. and (DeclProc.Parent is TInterfaceSection)
  3371. and (Proc.Parent.Parent=DeclProc.Parent.Parent))
  3372. then
  3373. begin
  3374. // both procs are defined in the same scope
  3375. if ProcNeedsImplProc(Proc) or (not ProcNeedsImplProc(DeclProc)) then
  3376. RaiseMsg(20170216151652,nDuplicateIdentifier,sDuplicateIdentifier,
  3377. [ProcName,GetElementSourcePosStr(DeclProc)],Proc.ProcType);
  3378. CheckProcSignatureMatch(DeclProc,Proc);
  3379. DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
  3380. DeclProcScope.ImplProc:=Proc;
  3381. ProcScope:=Proc.CustomData as TPasProcedureScope;
  3382. ProcScope.DeclarationProc:=DeclProc;
  3383. // remove ImplProc from scope
  3384. ParentScope:=Scopes[ScopeCount-2];
  3385. (ParentScope as TPasIdentifierScope).RemoveLocalIdentifier(Proc);
  3386. // replace arguments with declaration arguments
  3387. ReplaceProcScopeImplArgsWithDeclArgs(ProcScope);
  3388. end
  3389. else
  3390. begin
  3391. // give a hint, that proc is hiding DeclProc
  3392. LogMsg(20170216151656,mtHint,nFunctionHidesIdentifier,sFunctionHidesIdentifier,
  3393. [DeclProc.Name,GetElementSourcePosStr(DeclProc)],Proc.ProcType);
  3394. end;
  3395. end
  3396. else if El.Name<>'' then
  3397. begin
  3398. // finished proc type, e.g. type TProcedure = procedure;
  3399. end
  3400. else
  3401. RaiseNotYetImplemented(20160922163411,El.Parent);
  3402. end;
  3403. procedure TPasResolver.FinishMethodDeclHeader(Proc: TPasProcedure);
  3404. procedure VisibilityLowered(Proc, OverloadProc: TPasProcedure);
  3405. begin
  3406. LogMsg(20170325004215,mtNote,nVirtualMethodXHasLowerVisibility,
  3407. sVirtualMethodXHasLowerVisibility,[Proc.Name,
  3408. VisibilityNames[Proc.Visibility],OverloadProc.Parent.Name,
  3409. VisibilityNames[OverloadProc.Visibility]],Proc);
  3410. Proc.Visibility:=OverloadProc.Visibility;
  3411. end;
  3412. var
  3413. Abort: boolean;
  3414. ClassScope: TPasClassScope;
  3415. FindData: TFindOverloadProcData;
  3416. OverloadProc: TPasProcedure;
  3417. ProcScope: TPasProcedureScope;
  3418. begin
  3419. Proc.ProcType.IsOfObject:=true;
  3420. ProcScope:=TopScope as TPasProcedureScope;
  3421. ClassScope:=Scopes[ScopeCount-2] as TPasClassScope;
  3422. ProcScope.ClassScope:=ClassScope;
  3423. FindData:=Default(TFindOverloadProcData);
  3424. FindData.Proc:=Proc;
  3425. FindData.Args:=Proc.ProcType.Args;
  3426. Abort:=false;
  3427. ClassScope.IterateElements(Proc.Name,ClassScope,@OnFindOverloadProc,@FindData,Abort);
  3428. if FindData.FoundNonProc<>nil then
  3429. // proc hides a non proc -> duplicate
  3430. RaiseMsg(20170216151659,nDuplicateIdentifier,sDuplicateIdentifier,
  3431. [FindData.FoundNonProc.Name,GetElementSourcePosStr(FindData.FoundNonProc)],Proc.ProcType);
  3432. if FindData.Found=nil then
  3433. begin
  3434. // no overload
  3435. if Proc.IsOverride then
  3436. RaiseMsg(20170216151702,nNoMethodInAncestorToOverride,
  3437. sNoMethodInAncestorToOverride,[GetProcTypeDescription(Proc.ProcType)],Proc.ProcType);
  3438. end
  3439. else
  3440. begin
  3441. // overload found
  3442. OverloadProc:=FindData.Found;
  3443. if Proc.Parent=OverloadProc.Parent then
  3444. // overload in same scope -> duplicate
  3445. RaiseMsg(20170216151705,nDuplicateIdentifier,sDuplicateIdentifier,
  3446. [OverloadProc.Name,GetElementSourcePosStr(OverloadProc)],Proc.ProcType);
  3447. ProcScope.OverriddenProc:=OverloadProc;
  3448. if Proc.IsOverride then
  3449. begin
  3450. if (not OverloadProc.IsVirtual) and (not OverloadProc.IsOverride) then
  3451. // the OverloadProc fits the signature, but is not virtual
  3452. RaiseMsg(20170216151708,nNoMethodInAncestorToOverride,
  3453. sNoMethodInAncestorToOverride,[GetProcTypeDescription(Proc.ProcType)],Proc.ProcType);
  3454. // override a virtual method
  3455. CheckProcSignatureMatch(OverloadProc,Proc);
  3456. // check visibility
  3457. if Proc.Visibility<>OverloadProc.Visibility then
  3458. case Proc.Visibility of
  3459. visPrivate,visStrictPrivate:
  3460. if not (OverloadProc.Visibility in [visPrivate,visStrictPrivate]) then
  3461. VisibilityLowered(Proc,OverloadProc);
  3462. visProtected,visStrictProtected:
  3463. if not (OverloadProc.Visibility in [visPrivate,visProtected,visStrictPrivate,visStrictProtected]) then
  3464. VisibilityLowered(Proc,OverloadProc);
  3465. visPublic:
  3466. if not (OverloadProc.Visibility in [visPrivate..visPublic,visStrictPrivate,visStrictProtected]) then
  3467. VisibilityLowered(Proc,OverloadProc);
  3468. visPublished: ;
  3469. else
  3470. RaiseNotYetImplemented(20170325003315,Proc,'visibility');
  3471. end;
  3472. // check name case
  3473. if proFixCaseOfOverrides in Options then
  3474. Proc.Name:=OverloadProc.Name;
  3475. end
  3476. else if not Proc.IsReintroduced then
  3477. begin
  3478. // give a hint, that proc is hiding OverloadProc
  3479. LogMsg(20170216151712,mtHint,nFunctionHidesIdentifier,sFunctionHidesIdentifier,
  3480. [OverloadProc.Name,GetElementSourcePosStr(OverloadProc)],Proc.ProcType);
  3481. end;
  3482. end;
  3483. end;
  3484. procedure TPasResolver.FinishMethodImplHeader(ImplProc: TPasProcedure);
  3485. var
  3486. ProcName: String;
  3487. CurClassType: TPasClassType;
  3488. FindData: TFindOverloadProcData;
  3489. Abort: boolean;
  3490. ImplProcScope, DeclProcScope: TPasProcedureScope;
  3491. DeclProc: TPasProcedure;
  3492. CurClassScope: TPasClassScope;
  3493. SelfArg: TPasArgument;
  3494. p: Integer;
  3495. begin
  3496. if ImplProc.IsExternal then
  3497. RaiseMsg(20170216151715,nInvalidXModifierY,sInvalidXModifierY,[ImplProc.ElementTypeName,'external'],ImplProc);
  3498. if ImplProc.IsExported then
  3499. RaiseMsg(20170216151717,nInvalidXModifierY,sInvalidXModifierY,[ImplProc.ElementTypeName,'export'],ImplProc);
  3500. ProcName:=ImplProc.Name;
  3501. {$IFDEF VerbosePasResolver}
  3502. writeln('TPasResolver.FinishMethodBodyHeader searching declaration "',ProcName,'" ...');
  3503. {$ENDIF}
  3504. ImplProc.ProcType.IsOfObject:=true;
  3505. repeat
  3506. p:=Pos('.',ProcName);
  3507. if p<1 then break;
  3508. Delete(ProcName,1,p);
  3509. until false;
  3510. // search ImplProc in class
  3511. if not IsValidIdent(ProcName) then
  3512. RaiseNotYetImplemented(20160922163421,ImplProc.ProcType);
  3513. // search proc in class
  3514. ImplProcScope:=ImplProc.CustomData as TPasProcedureScope;
  3515. CurClassScope:=ImplProcScope.ClassScope;
  3516. if CurClassScope=nil then
  3517. RaiseInternalError(20161013172346);
  3518. CurClassType:=CurClassScope.Element as TPasClassType;
  3519. FindData:=Default(TFindOverloadProcData);
  3520. FindData.Proc:=ImplProc;
  3521. FindData.Args:=ImplProc.ProcType.Args;
  3522. FindData.OnlyScope:=CurClassScope;
  3523. Abort:=false;
  3524. CurClassScope.IterateElements(ProcName,CurClassScope,@OnFindOverloadProc,@FindData,Abort);
  3525. if FindData.Found=nil then
  3526. RaiseIdentifierNotFound(20170216151720,ImplProc.Name,ImplProc.ProcType);
  3527. // connect method declaration and body
  3528. DeclProc:=FindData.Found;
  3529. if DeclProc.IsAbstract then
  3530. RaiseMsg(20170216151722,nAbstractMethodsMustNotHaveImplementation,sAbstractMethodsMustNotHaveImplementation,[],ImplProc);
  3531. if DeclProc.IsExternal then
  3532. RaiseXExpectedButYFound(20170216151725,'method','external method',ImplProc);
  3533. CheckProcSignatureMatch(DeclProc,ImplProc);
  3534. ImplProcScope.DeclarationProc:=DeclProc;
  3535. DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
  3536. DeclProcScope.ImplProc:=ImplProc;
  3537. // replace arguments in scope with declaration arguments
  3538. ReplaceProcScopeImplArgsWithDeclArgs(ImplProcScope);
  3539. if not DeclProc.IsStatic then
  3540. begin
  3541. // add 'Self'
  3542. if (DeclProc.ClassType=TPasClassConstructor)
  3543. or (DeclProc.ClassType=TPasClassDestructor)
  3544. or (DeclProc.ClassType=TPasClassProcedure)
  3545. or (DeclProc.ClassType=TPasClassFunction) then
  3546. begin
  3547. if not DeclProc.IsStatic then
  3548. begin
  3549. // 'Self' in a class proc is the hidden classtype argument
  3550. SelfArg:=TPasArgument.Create('Self',DeclProc);
  3551. ImplProcScope.SelfArg:=SelfArg;
  3552. SelfArg.Access:=argConst;
  3553. SelfArg.ArgType:=CurClassScope.CanonicalClassOf;
  3554. SelfArg.ArgType.AddRef;
  3555. AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
  3556. end;
  3557. end
  3558. else
  3559. begin
  3560. // 'Self' in a proc is the hidden instance argument
  3561. SelfArg:=TPasArgument.Create('Self',DeclProc);
  3562. ImplProcScope.SelfArg:=SelfArg;
  3563. SelfArg.Access:=argConst;
  3564. SelfArg.ArgType:=CurClassType;
  3565. CurClassType.AddRef;
  3566. AddIdentifier(ImplProcScope,'Self',SelfArg,pikSimple);
  3567. end;
  3568. end;
  3569. {$IFDEF VerbosePasResolver}
  3570. writeln('TPasResolver.FinishMethodBodyHeader END of searching proc "',ImplProc.Name,'" ...');
  3571. {$ENDIF}
  3572. end;
  3573. procedure TPasResolver.FinishExceptOnExpr;
  3574. var
  3575. El: TPasImplExceptOn;
  3576. ResolvedType: TPasResolverResult;
  3577. begin
  3578. CheckTopScope(TPasExceptOnScope);
  3579. El:=TPasImplExceptOn(FTopScope.Element);
  3580. ComputeElement(El.TypeEl,ResolvedType,[rcSkipTypeAlias,rcType]);
  3581. CheckIsClass(El.TypeEl,ResolvedType);
  3582. end;
  3583. procedure TPasResolver.FinishExceptOnStatement;
  3584. begin
  3585. //writeln('TPasResolver.FinishExceptOnStatement START');
  3586. CheckTopScope(TPasExceptOnScope);
  3587. ResolveImplElement(TPasImplExceptOn(FTopScope.Element).Body);
  3588. PopScope;
  3589. end;
  3590. procedure TPasResolver.FinishDeclaration(El: TPasElement);
  3591. var
  3592. C: TClass;
  3593. begin
  3594. C:=El.ClassType;
  3595. if C=TPasVariable then
  3596. FinishVariable(TPasVariable(El))
  3597. else if C=TPasProperty then
  3598. FinishPropertyOfClass(TPasProperty(El))
  3599. else if C=TPasArgument then
  3600. FinishArgument(TPasArgument(El))
  3601. else
  3602. begin
  3603. {$IFDEF VerbosePasResolver}
  3604. writeln('TPasResolver.FinishDeclaration ',GetObjName(El));
  3605. {$ENDIF}
  3606. end;
  3607. end;
  3608. procedure TPasResolver.FinishVariable(El: TPasVariable);
  3609. begin
  3610. if (El.Visibility=visPublished) then
  3611. begin
  3612. if [vmClass,vmStatic,vmCVar]*El.VarModifiers<>[] then
  3613. RaiseMsg(20170403223837,nSymbolCannotBePublished,sSymbolCannotBePublished,[],El);
  3614. end;
  3615. if El.Expr<>nil then
  3616. begin
  3617. ResolveExpr(El.Expr,rraRead);
  3618. CheckAssignCompatibility(El,El.Expr,true);
  3619. end;
  3620. EmitTypeHints(El,El.VarType);
  3621. end;
  3622. procedure TPasResolver.FinishPropertyOfClass(PropEl: TPasProperty);
  3623. var
  3624. PropType: TPasType;
  3625. ClassScope: TPasClassScope;
  3626. procedure GetPropType;
  3627. var
  3628. AncEl: TPasElement;
  3629. AncProp: TPasProperty;
  3630. begin
  3631. if PropType<>nil then exit;
  3632. AncEl:=nil;
  3633. if ClassScope.AncestorScope<>nil then
  3634. AncEl:=ClassScope.AncestorScope.FindElement(PropEl.Name);
  3635. if AncEl is TPasProperty then
  3636. begin
  3637. // override or redeclaration property
  3638. AncProp:=TPasProperty(AncEl);
  3639. TPasPropertyScope(PropEl.CustomData).AncestorProp:=AncProp;
  3640. AncProp.AddRef;
  3641. if proFixCaseOfOverrides in Options then
  3642. PropEl.Name:=AncProp.Name;
  3643. end
  3644. else
  3645. AncProp:=nil;
  3646. if PropEl.VarType<>nil then
  3647. begin
  3648. // new property or redeclaration
  3649. PropType:=PropEl.VarType;
  3650. end
  3651. else
  3652. begin
  3653. // property override
  3654. if AncProp=nil then
  3655. RaiseMsg(20170216151741,nNoPropertyFoundToOverride,sNoPropertyFoundToOverride,[],PropEl);
  3656. // check property versus class property
  3657. if PropEl.ClassType<>AncProp.ClassType then
  3658. RaiseXExpectedButYFound(20170216151744,AncProp.ElementTypeName,PropEl.ElementTypeName,PropEl);
  3659. // get inherited type
  3660. PropType:=GetPasPropertyType(AncProp);
  3661. // update DefaultProperty
  3662. if (ClassScope.DefaultProperty=AncProp) then
  3663. ClassScope.DefaultProperty:=PropEl;
  3664. end;
  3665. end;
  3666. function GetAccessor(Expr: TPasExpr): TPasElement;
  3667. var
  3668. Prim: TPrimitiveExpr;
  3669. DeclEl: TPasElement;
  3670. Identifier: TPasIdentifier;
  3671. Scope: TPasIdentifierScope;
  3672. begin
  3673. if Expr.ClassType=TBinaryExpr then
  3674. begin
  3675. if (TBinaryExpr(Expr).left is TPrimitiveExpr) then
  3676. begin
  3677. Prim:=TPrimitiveExpr(TBinaryExpr(Expr).left);
  3678. if Prim.Kind<>pekIdent then
  3679. RaiseXExpectedButYFound(20170216151746,'class',Prim.Value,Prim);
  3680. Scope:=TopScope as TPasIdentifierScope;
  3681. // search in class and ancestors, not in unit interface
  3682. Identifier:=Scope.FindIdentifier(Prim.Value);
  3683. if Identifier=nil then
  3684. RaiseIdentifierNotFound(20170216151749,Prim.Value,Prim);
  3685. DeclEl:=Identifier.Element;
  3686. if DeclEl.ClassType<>TPasClassType then
  3687. RaiseXExpectedButYFound(20170216151752,'class',DeclEl.ElementTypeName,Prim);
  3688. CreateReference(DeclEl,Prim,rraRead);
  3689. end
  3690. else
  3691. RaiseMsg(20170216151754,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TBinaryExpr(Expr).OpCode]],Expr);
  3692. if TBinaryExpr(Expr).OpCode<>eopSubIdent then
  3693. RaiseMsg(20170216151757,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TBinaryExpr(Expr).OpCode]],Expr);
  3694. PushClassDotScope(TPasClassType(DeclEl));
  3695. Expr:=TBinaryExpr(Expr).right;
  3696. Result:=GetAccessor(Expr);
  3697. PopScope;
  3698. end
  3699. else if Expr.ClassType=TPrimitiveExpr then
  3700. begin
  3701. Prim:=TPrimitiveExpr(Expr);
  3702. if Prim.Kind<>pekIdent then
  3703. RaiseXExpectedButYFound(20170216151800,'identifier',Prim.Value,Prim);
  3704. Scope:=TopScope as TPasIdentifierScope;
  3705. // search in class and ancestors, not in unit interface
  3706. Identifier:=Scope.FindIdentifier(Prim.Value);
  3707. if Identifier=nil then
  3708. RaiseIdentifierNotFound(20170216151803,Prim.Value,Prim);
  3709. DeclEl:=Identifier.Element;
  3710. CreateReference(DeclEl,Prim,rraRead);
  3711. Result:=DeclEl;
  3712. end
  3713. else
  3714. RaiseNotYetImplemented(20160922163436,Expr);
  3715. end;
  3716. procedure CheckArgs(Proc: TPasProcedure; ErrorEl: TPasElement);
  3717. var
  3718. ArgNo: Integer;
  3719. PropArg, ProcArg: TPasArgument;
  3720. PropArgResolved, ProcArgResolved: TPasResolverResult;
  3721. begin
  3722. ArgNo:=0;
  3723. while ArgNo<PropEl.Args.Count do
  3724. begin
  3725. if ArgNo>=Proc.ProcType.Args.Count then
  3726. RaiseMsg(20170216151805,nWrongNumberOfParametersForCallTo,
  3727. sWrongNumberOfParametersForCallTo,[Proc.Name],ErrorEl);
  3728. PropArg:=TPasArgument(PropEl.Args[ArgNo]);
  3729. ProcArg:=TPasArgument(Proc.ProcType.Args[ArgNo]);
  3730. inc(ArgNo);
  3731. // check access: var, const, ...
  3732. if PropArg.Access<>ProcArg.Access then
  3733. RaiseMsg(20170216151808,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  3734. [IntToStr(ArgNo),AccessDescriptions[ProcArg.Access],
  3735. AccessDescriptions[PropArg.Access]],ErrorEl);
  3736. // check typed
  3737. if PropArg.ArgType=nil then
  3738. begin
  3739. if ProcArg.ArgType<>nil then
  3740. RaiseMsg(20170216151811,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  3741. [IntToStr(ArgNo),ProcArg.ArgType.ElementTypeName,'untyped'],ErrorEl);
  3742. end
  3743. else if ProcArg.ArgType=nil then
  3744. RaiseMsg(20170216151813,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  3745. [IntToStr(ArgNo),'untyped',PropArg.ArgType.ElementTypeName],ErrorEl)
  3746. else
  3747. begin
  3748. ComputeElement(PropArg,PropArgResolved,[rcNoImplicitProc]);
  3749. ComputeElement(ProcArg,ProcArgResolved,[rcNoImplicitProc]);
  3750. if (PropArgResolved.BaseType<>ProcArgResolved.BaseType) then
  3751. RaiseMsg(20170216151816,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  3752. [IntToStr(ArgNo),BaseTypeNames[ProcArgResolved.BaseType],BaseTypeNames[PropArgResolved.BaseType]],ErrorEl);
  3753. if PropArgResolved.TypeEl=nil then
  3754. RaiseInternalError(20161010125255);
  3755. if ProcArgResolved.TypeEl=nil then
  3756. RaiseInternalError(20161010125304);
  3757. if not IsSameType(PropArgResolved.TypeEl,ProcArgResolved.TypeEl,true) then
  3758. RaiseIncompatibleType(20170216151819,nIncompatibleTypeArgNo,
  3759. [IntToStr(ArgNo)],ProcArgResolved.TypeEl,PropArgResolved.TypeEl,ErrorEl);
  3760. end;
  3761. end;
  3762. end;
  3763. var
  3764. ResultType, TypeEl: TPasType;
  3765. CurClassType: TPasClassType;
  3766. AccEl: TPasElement;
  3767. Proc: TPasProcedure;
  3768. Arg: TPasArgument;
  3769. PropArgCount: Integer;
  3770. PropTypeResolved, DefaultResolved: TPasResolverResult;
  3771. m: TVariableModifier;
  3772. begin
  3773. CheckTopScope(TPasPropertyScope);
  3774. PopScope;
  3775. if PropEl.Visibility=visPublished then
  3776. for m in PropEl.VarModifiers do
  3777. if not (m in [vmExternal]) then
  3778. RaiseMsg(20170403224112,nInvalidXModifierY,sInvalidXModifierY,
  3779. ['published property','"'+VariableModifierNames[m]+'"'],PropEl);
  3780. PropType:=nil;
  3781. CurClassType:=PropEl.Parent as TPasClassType;
  3782. ClassScope:=CurClassType.CustomData as TPasClassScope;
  3783. GetPropType;
  3784. if PropEl.IndexExpr<>nil then
  3785. begin
  3786. ResolveExpr(PropEl.IndexExpr,rraRead);
  3787. RaiseNotYetImplemented(20160922163439,PropEl.IndexExpr);
  3788. end;
  3789. if PropEl.ReadAccessor<>nil then
  3790. begin
  3791. // check compatibility
  3792. AccEl:=GetAccessor(PropEl.ReadAccessor);
  3793. if (AccEl.ClassType=TPasVariable) or (AccEl.ClassType=TPasConst) then
  3794. begin
  3795. if PropEl.Args.Count>0 then
  3796. RaiseXExpectedButYFound(20170216151823,'function',AccEl.ElementTypeName,PropEl.ReadAccessor);
  3797. if not IsSameType(TPasVariable(AccEl).VarType,PropType,true) then
  3798. RaiseIncompatibleType(20170216151826,nIncompatibleTypesGotExpected,
  3799. [],PropType,TPasVariable(AccEl).VarType,PropEl.ReadAccessor);
  3800. if (vmClass in PropEl.VarModifiers)<>(vmClass in TPasVariable(AccEl).VarModifiers) then
  3801. if vmClass in PropEl.VarModifiers then
  3802. RaiseXExpectedButYFound(20170216151828,'class var','var',PropEl.ReadAccessor)
  3803. else
  3804. RaiseXExpectedButYFound(20170216151831,'var','class var',PropEl.ReadAccessor);
  3805. end
  3806. else if AccEl is TPasProcedure then
  3807. begin
  3808. // check function
  3809. Proc:=TPasProcedure(AccEl);
  3810. if (vmClass in PropEl.VarModifiers) then
  3811. begin
  3812. if Proc.ClassType<>TPasClassFunction then
  3813. RaiseXExpectedButYFound(20170216151834,'class function',Proc.ElementTypeName,PropEl.ReadAccessor);
  3814. if Proc.IsStatic=(proClassPropertyNonStatic in Options) then
  3815. if Proc.IsStatic then
  3816. RaiseMsg(20170216151837,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.ReadAccessor)
  3817. else
  3818. RaiseMsg(20170216151839,nClassPropertyAccessorMustBeStatic,sClassPropertyAccessorMustBeStatic,[],PropEl.ReadAccessor);
  3819. end
  3820. else
  3821. begin
  3822. if Proc.ClassType<>TPasFunction then
  3823. RaiseXExpectedButYFound(20170216151842,'function',Proc.ElementTypeName,PropEl.ReadAccessor);
  3824. end;
  3825. // check function result type
  3826. ResultType:=TPasFunction(Proc).FuncType.ResultEl.ResultType;
  3827. if not IsSameType(ResultType,PropType,true) then
  3828. RaiseXExpectedButYFound(20170216151844,'function result '+GetTypeDescription(PropType,true),
  3829. GetTypeDescription(ResultType,true),PropEl.ReadAccessor);
  3830. // check args
  3831. CheckArgs(Proc,PropEl.ReadAccessor);
  3832. if Proc.ProcType.Args.Count<>PropEl.Args.Count then
  3833. RaiseMsg(20170216151847,nWrongNumberOfParametersForCallTo,sWrongNumberOfParametersForCallTo,
  3834. [Proc.Name],PropEl.ReadAccessor);
  3835. end
  3836. else
  3837. RaiseXExpectedButYFound(20170216151850,'variable',AccEl.ElementTypeName,PropEl.ReadAccessor);
  3838. end;
  3839. if PropEl.WriteAccessor<>nil then
  3840. begin
  3841. // check compatibility
  3842. AccEl:=GetAccessor(PropEl.WriteAccessor);
  3843. if AccEl.ClassType=TPasVariable then
  3844. begin
  3845. if PropEl.Args.Count>0 then
  3846. RaiseXExpectedButYFound(20170216151852,'procedure',AccEl.ElementTypeName,PropEl.WriteAccessor);
  3847. if not IsSameType(TPasVariable(AccEl).VarType,PropType,true) then
  3848. RaiseIncompatibleType(20170216151855,nIncompatibleTypesGotExpected,
  3849. [],PropType,TPasVariable(AccEl).VarType,PropEl.WriteAccessor);
  3850. if (vmClass in PropEl.VarModifiers)<>(vmClass in TPasVariable(AccEl).VarModifiers) then
  3851. if vmClass in PropEl.VarModifiers then
  3852. RaiseXExpectedButYFound(20170216151858,'class var','var',PropEl.WriteAccessor)
  3853. else
  3854. RaiseXExpectedButYFound(20170216151900,'var','class var',PropEl.WriteAccessor);
  3855. end
  3856. else if AccEl is TPasProcedure then
  3857. begin
  3858. // check procedure
  3859. Proc:=TPasProcedure(AccEl);
  3860. if (vmClass in PropEl.VarModifiers) then
  3861. begin
  3862. if Proc.ClassType<>TPasClassProcedure then
  3863. RaiseXExpectedButYFound(20170216151903,'class procedure',Proc.ElementTypeName,PropEl.WriteAccessor);
  3864. if Proc.IsStatic=(proClassPropertyNonStatic in Options) then
  3865. if Proc.IsStatic then
  3866. RaiseMsg(20170216151905,nClassPropertyAccessorMustNotBeStatic,sClassPropertyAccessorMustNotBeStatic,[],PropEl.WriteAccessor)
  3867. else
  3868. RaiseMsg(20170216151906,nClassPropertyAccessorMustBeStatic,sClassPropertyAccessorMustBeStatic,[],PropEl.WriteAccessor);
  3869. end
  3870. else
  3871. begin
  3872. if Proc.ClassType<>TPasProcedure then
  3873. RaiseXExpectedButYFound(20170216151910,'procedure',Proc.ElementTypeName,PropEl.WriteAccessor);
  3874. end;
  3875. // check args
  3876. CheckArgs(Proc,PropEl.ReadAccessor);
  3877. // ToDo: check index arg
  3878. // check write arg
  3879. PropArgCount:=PropEl.Args.Count;
  3880. if Proc.ProcType.Args.Count<>PropArgCount+1 then
  3881. RaiseMsg(20170216151913,nWrongNumberOfParametersForCallTo,sWrongNumberOfParametersForCallTo,
  3882. [Proc.Name],PropEl.WriteAccessor);
  3883. Arg:=TPasArgument(Proc.ProcType.Args[PropArgCount]);
  3884. if not (Arg.Access in [argDefault,argConst]) then
  3885. RaiseMsg(20170216151917,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  3886. [IntToStr(PropArgCount+1),AccessDescriptions[Arg.Access],
  3887. AccessDescriptions[argConst]],PropEl.WriteAccessor);
  3888. if not IsSameType(Arg.ArgType,PropType,true) then
  3889. RaiseIncompatibleType(20170216151919,nIncompatibleTypeArgNo,
  3890. [IntToStr(PropArgCount+1)],Arg.ArgType,PropType,PropEl.WriteAccessor);
  3891. end
  3892. else
  3893. RaiseXExpectedButYFound(20170216151921,'variable',AccEl.ElementTypeName,PropEl.WriteAccessor);
  3894. end;
  3895. if PropEl.ImplementsFunc<>nil then
  3896. begin
  3897. ResolveExpr(PropEl.ImplementsFunc,rraRead);
  3898. // ToDo: check compatibility
  3899. RaiseNotYetImplemented(20170409213850,PropEl.ImplementsFunc);
  3900. end;
  3901. if PropEl.StoredAccessor<>nil then
  3902. begin
  3903. // check compatibility
  3904. AccEl:=GetAccessor(PropEl.StoredAccessor);
  3905. if (AccEl.ClassType=TPasVariable) or (AccEl.ClassType=TPasConst) then
  3906. begin
  3907. if PropEl.IndexExpr<>nil then
  3908. RaiseNotYetImplemented(20170409214006,PropEl.StoredAccessor,'stored with index');
  3909. TypeEl:=TPasVariable(AccEl).VarType;
  3910. // ToDo: TypeEl=nil TPasConst false/true
  3911. TypeEl:=ResolveAliasType(TypeEl);
  3912. if not IsBaseType(TypeEl,btBoolean,true) then
  3913. RaiseIncompatibleType(20170409214300,nIncompatibleTypesGotExpected,
  3914. [],TypeEl,BaseTypes[btBoolean],PropEl.StoredAccessor);
  3915. if (vmClass in PropEl.VarModifiers)<>(vmClass in TPasVariable(AccEl).VarModifiers) then
  3916. if vmClass in PropEl.VarModifiers then
  3917. RaiseXExpectedButYFound(20170409214351,'class var','var',PropEl.StoredAccessor)
  3918. else
  3919. RaiseXExpectedButYFound(20170409214359,'var','class var',PropEl.StoredAccessor);
  3920. end
  3921. else if AccEl is TPasProcedure then
  3922. begin
  3923. // check function
  3924. Proc:=TPasProcedure(AccEl);
  3925. if Proc.ClassType<>TPasFunction then
  3926. RaiseXExpectedButYFound(20170216151925,'function',Proc.ElementTypeName,PropEl.StoredAccessor);
  3927. // check function result type
  3928. ResultType:=TPasFunction(Proc).FuncType.ResultEl.ResultType;
  3929. if not IsBaseType(ResultType,btBoolean,true) then
  3930. RaiseXExpectedButYFound(20170216151929,'function: boolean',
  3931. 'function:'+GetTypeDescription(ResultType),PropEl.StoredAccessor);
  3932. // check arg count
  3933. if Proc.ProcType.Args.Count<>0 then
  3934. RaiseMsg(20170216151932,nWrongNumberOfParametersForCallTo,sWrongNumberOfParametersForCallTo,
  3935. [Proc.Name],PropEl.StoredAccessor);
  3936. end
  3937. else
  3938. RaiseXExpectedButYFound(20170216151935,'function: boolean',AccEl.ElementTypeName,PropEl.StoredAccessor);
  3939. end;
  3940. if PropEl.DefaultExpr<>nil then
  3941. begin
  3942. // check compatibility with type
  3943. ResolveExpr(PropEl.DefaultExpr,rraRead);
  3944. ComputeElement(PropEl.DefaultExpr,DefaultResolved,[rcConstant]);
  3945. ComputeElement(PropType,PropTypeResolved,[rcType]);
  3946. PropTypeResolved.IdentEl:=PropEl;
  3947. PropTypeResolved.Flags:=[rrfReadable];
  3948. CheckEqualResCompatibility(PropTypeResolved,DefaultResolved,PropEl.DefaultExpr,true);
  3949. end;
  3950. if PropEl.IsDefault then
  3951. begin
  3952. // set default array property
  3953. if (ClassScope.DefaultProperty<>nil)
  3954. and (ClassScope.DefaultProperty.Parent=PropEl.Parent) then
  3955. RaiseMsg(20170216151938,nOnlyOneDefaultPropertyIsAllowed,sOnlyOneDefaultPropertyIsAllowed,[],PropEl);
  3956. ClassScope.DefaultProperty:=PropEl;
  3957. end;
  3958. EmitTypeHints(PropEl,PropEl.VarType);
  3959. end;
  3960. procedure TPasResolver.FinishArgument(El: TPasArgument);
  3961. begin
  3962. if El.ValueExpr<>nil then
  3963. begin
  3964. ResolveExpr(El.ValueExpr,rraRead);
  3965. if El.ArgType<>nil then
  3966. CheckAssignCompatibility(El,El.ValueExpr,true);
  3967. end;
  3968. EmitTypeHints(El,El.ArgType);
  3969. end;
  3970. procedure TPasResolver.FinishAncestors(aClass: TPasClassType);
  3971. // called when the ancestor and interface list of a class has been parsed,
  3972. // before parsing the class elements
  3973. var
  3974. AncestorEl: TPasClassType;
  3975. ClassScope, AncestorClassScope: TPasClassScope;
  3976. DirectAncestor, AncestorType, El: TPasType;
  3977. i: Integer;
  3978. aModifier: String;
  3979. IsSealed: Boolean;
  3980. CanonicalSelf: TPasClassOfType;
  3981. begin
  3982. if aClass.IsForward then
  3983. exit;
  3984. if aClass.ObjKind<>okClass then
  3985. RaiseNotYetImplemented(20161010174638,aClass,'Kind='+ObjKindNames[aClass.ObjKind]);
  3986. IsSealed:=false;
  3987. for i:=0 to aClass.Modifiers.Count-1 do
  3988. begin
  3989. aModifier:=lowercase(aClass.Modifiers[i]);
  3990. case aModifier of
  3991. 'sealed': IsSealed:=true;
  3992. else
  3993. RaiseMsg(20170320190619,nIllegalQualifier,sIllegalQualifier,[aClass.Modifiers[i]],aClass);
  3994. end;
  3995. end;
  3996. DirectAncestor:=aClass.AncestorType;
  3997. AncestorType:=ResolveAliasType(DirectAncestor);
  3998. if AncestorType=nil then
  3999. begin
  4000. if (CompareText(aClass.Name,'TObject')=0) or aClass.IsExternal then
  4001. begin
  4002. // ok, no ancestors
  4003. AncestorEl:=nil;
  4004. end else begin
  4005. // search default ancestor TObject
  4006. AncestorEl:=TPasClassType(FindElementWithoutParams('TObject',aClass,false));
  4007. if not (AncestorEl is TPasClassType) then
  4008. RaiseXExpectedButYFound(20170216151941,'class type',GetObjName(AncestorEl),aClass);
  4009. if DirectAncestor=nil then
  4010. DirectAncestor:=AncestorEl;
  4011. end;
  4012. end
  4013. else if AncestorType.ClassType<>TPasClassType then
  4014. RaiseXExpectedButYFound(20170216151944,'class type',GetTypeDescription(AncestorType),aClass)
  4015. else if aClass=AncestorType then
  4016. RaiseMsg(20170525125854,nAncestorCycleDetected,sAncestorCycleDetected,[],aClass)
  4017. else
  4018. begin
  4019. AncestorEl:=TPasClassType(AncestorType);
  4020. EmitTypeHints(aClass,AncestorEl);
  4021. end;
  4022. AncestorClassScope:=nil;
  4023. if AncestorEl=nil then
  4024. begin
  4025. // root class e.g. TObject
  4026. end
  4027. else
  4028. begin
  4029. // inherited class
  4030. if AncestorEl.IsForward then
  4031. RaiseMsg(20170216151947,nCantUseForwardDeclarationAsAncestor,
  4032. sCantUseForwardDeclarationAsAncestor,[AncestorEl.Name],aClass);
  4033. if aClass.IsExternal and not AncestorEl.IsExternal then
  4034. RaiseMsg(20170321144035,nAncestorIsNotExternal,sAncestorIsNotExternal,
  4035. [AncestorEl.Name],aClass);
  4036. AncestorClassScope:=AncestorEl.CustomData as TPasClassScope;
  4037. if pcsfSealed in AncestorClassScope.Flags then
  4038. RaiseMsg(20170320191735,nCannotCreateADescendantOfTheSealedClass,
  4039. sCannotCreateADescendantOfTheSealedClass,[AncestorEl.Name],aClass);
  4040. // check for cycle
  4041. El:=AncestorEl;
  4042. repeat
  4043. if El=aClass then
  4044. RaiseMsg(20170216151949,nAncestorCycleDetected,sAncestorCycleDetected,[],aClass);
  4045. if (El.ClassType=TPasAliasType)
  4046. or (El.ClassType=TPasTypeAliasType)
  4047. then
  4048. El:=TPasAliasType(El).DestType
  4049. else if El.ClassType=TPasClassType then
  4050. El:=TPasClassType(El).AncestorType;
  4051. until El=nil;
  4052. end;
  4053. // start scope for elements
  4054. {$IFDEF VerbosePasResolver}
  4055. //writeln('TPasResolver.FinishAncestors ',GetObjName(aClass.CustomData));
  4056. {$ENDIF}
  4057. PushScope(aClass,ScopeClass_Class);
  4058. ClassScope:=TPasClassScope(TopScope);
  4059. ClassScope.VisibilityContext:=aClass;
  4060. Include(ClassScope.Flags,pcsfAncestorResolved);
  4061. if IsSealed then
  4062. Include(ClassScope.Flags,pcsfSealed);
  4063. ClassScope.DirectAncestor:=DirectAncestor;
  4064. if AncestorEl<>nil then
  4065. begin
  4066. ClassScope.AncestorScope:=AncestorEl.CustomData as TPasClassScope;
  4067. ClassScope.DefaultProperty:=ClassScope.AncestorScope.DefaultProperty;
  4068. end;
  4069. // create canonical class-of for the "Self" in class functions
  4070. CanonicalSelf:=TPasClassOfType.Create('Self',aClass);
  4071. ClassScope.CanonicalClassOf:=CanonicalSelf;
  4072. CanonicalSelf.DestType:=aClass;
  4073. aClass.AddRef;
  4074. CanonicalSelf.Visibility:=visStrictPrivate;
  4075. CanonicalSelf.SourceFilename:=aClass.SourceFilename;
  4076. CanonicalSelf.SourceLinenumber:=aClass.SourceLinenumber;
  4077. end;
  4078. procedure TPasResolver.FinishPropertyParamAccess(Params: TParamsExpr;
  4079. Prop: TPasProperty);
  4080. var
  4081. i: Integer;
  4082. ParamAccess: TResolvedRefAccess;
  4083. begin
  4084. for i:=0 to length(Params.Params)-1 do
  4085. begin
  4086. ParamAccess:=rraRead;
  4087. if i<Prop.Args.Count then
  4088. case TPasArgument(Prop.Args[i]).Access of
  4089. argVar: ParamAccess:=rraVarParam;
  4090. argOut: ParamAccess:=rraOutParam;
  4091. end;
  4092. AccessExpr(Params.Params[i],ParamAccess);
  4093. end;
  4094. end;
  4095. procedure TPasResolver.EmitTypeHints(PosEl: TPasElement; aType: TPasType);
  4096. begin
  4097. while aType<>nil do
  4098. begin
  4099. if EmitElementHints(PosEl,aType) then
  4100. exit; // give only hints for the nearest
  4101. if aType.InheritsFrom(TPasAliasType) then
  4102. aType:=TPasAliasType(aType).DestType
  4103. else if aType.ClassType=TPasPointerType then
  4104. aType:=TPasPointerType(aType).DestType
  4105. else if (aType.ClassType=TPasClassType) and TPasClassType(aType).IsForward
  4106. and (aType.CustomData<>nil) then
  4107. aType:=TPasType((aType.CustomData as TResolvedReference).Declaration)
  4108. else
  4109. exit;
  4110. end;
  4111. end;
  4112. function TPasResolver.EmitElementHints(PosEl, El: TPasElement): boolean;
  4113. begin
  4114. if El.Hints=[] then exit(false);
  4115. Result:=true;
  4116. if hDeprecated in El.Hints then
  4117. begin
  4118. if El.HintMessage<>'' then
  4119. LogMsg(20170422160807,mtWarning,nSymbolXIsDeprecatedY,sSymbolXIsDeprecatedY,
  4120. [El.Name,El.HintMessage],PosEl)
  4121. else
  4122. LogMsg(20170419190434,mtWarning,nSymbolXIsDeprecated,sSymbolXIsDeprecated,
  4123. [El.Name],PosEl);
  4124. end;
  4125. if hLibrary in El.Hints then
  4126. LogMsg(20170419190426,mtWarning,nSymbolXBelongsToALibrary,sSymbolXBelongsToALibrary,
  4127. [El.Name],PosEl);
  4128. if hPlatform in El.Hints then
  4129. LogMsg(20170419185916,mtWarning,nSymbolXIsNotPortable,sSymbolXIsNotPortable,
  4130. [El.Name],PosEl);
  4131. if hExperimental in El.Hints then
  4132. LogMsg(20170419190111,mtWarning,nSymbolXIsExperimental,sSymbolXIsExperimental,
  4133. [El.Name],PosEl);
  4134. if hUnimplemented in El.Hints then
  4135. LogMsg(20170419190317,mtWarning,nSymbolXIsNotImplemented,sSymbolXIsNotImplemented,
  4136. [El.Name],PosEl);
  4137. end;
  4138. procedure TPasResolver.ReplaceProcScopeImplArgsWithDeclArgs(
  4139. ImplProcScope: TPasProcedureScope);
  4140. var
  4141. DeclProc, ImplProc: TPasProcedure;
  4142. DeclArgs, ImplArgs: TFPList;
  4143. i: Integer;
  4144. DeclArg, ImplArg: TPasArgument;
  4145. Identifier: TPasIdentifier;
  4146. begin
  4147. ImplProc:=ImplProcScope.Element as TPasProcedure;
  4148. ImplArgs:=ImplProc.ProcType.Args;
  4149. DeclProc:=ImplProcScope.DeclarationProc;
  4150. DeclArgs:=DeclProc.ProcType.Args;
  4151. for i:=0 to DeclArgs.Count-1 do
  4152. begin
  4153. DeclArg:=TPasArgument(DeclArgs[i]);
  4154. if i<ImplArgs.Count then
  4155. begin
  4156. ImplArg:=TPasArgument(ImplArgs[i]);
  4157. Identifier:=ImplProcScope.FindLocalIdentifier(DeclArg.Name);
  4158. //writeln('TPasResolver.ReplaceProcScopeImplArgsWithDeclArgs i=',i,' replacing ',GetObjName(ImplArg),' with ',GetObjName(DeclArg));
  4159. if Identifier.Element<>ImplArg then
  4160. RaiseInternalError(20170203161659,GetObjName(DeclArg)+' '+GetObjName(ImplArg));
  4161. Identifier.Element:=DeclArg;
  4162. Identifier.Identifier:=DeclArg.Name;
  4163. end
  4164. else
  4165. RaiseNotYetImplemented(20170203161826,ImplProc);
  4166. end;
  4167. if DeclProc is TPasFunction then
  4168. begin
  4169. // replace 'Result'
  4170. Identifier:=ImplProcScope.FindLocalIdentifier(ResolverResultVar);
  4171. if Identifier.Element is TPasResultElement then
  4172. Identifier.Element:=TPasFunction(DeclProc).FuncType.ResultEl;
  4173. end;
  4174. end;
  4175. procedure TPasResolver.CheckConditionExpr(El: TPasExpr;
  4176. const ResolvedEl: TPasResolverResult);
  4177. begin
  4178. if ResolvedEl.BaseType<>btBoolean then
  4179. RaiseMsg(20170216152135,nXExpectedButYFound,sXExpectedButYFound,
  4180. [BaseTypeNames[btBoolean],BaseTypeNames[ResolvedEl.BaseType]],El);
  4181. end;
  4182. procedure TPasResolver.CheckProcSignatureMatch(DeclProc, ImplProc: TPasProcedure
  4183. );
  4184. var
  4185. i: Integer;
  4186. DeclArgs, ImplArgs: TFPList;
  4187. DeclName, ImplName: String;
  4188. ImplResult, DeclResult: TPasType;
  4189. begin
  4190. if ImplProc.ClassType<>DeclProc.ClassType then
  4191. RaiseXExpectedButYFound(20170216151729,DeclProc.TypeName,ImplProc.TypeName,ImplProc);
  4192. if ImplProc.CallingConvention<>DeclProc.CallingConvention then
  4193. RaiseMsg(20170216151731,nCallingConventionMismatch,sCallingConventionMismatch,[],ImplProc);
  4194. if ImplProc is TPasFunction then
  4195. begin
  4196. // check result type
  4197. ImplResult:=TPasFunction(ImplProc).FuncType.ResultEl.ResultType;
  4198. DeclResult:=TPasFunction(DeclProc).FuncType.ResultEl.ResultType;
  4199. if not CheckProcArgTypeCompatibility(ImplResult,DeclResult) then
  4200. RaiseIncompatibleType(20170216151734,nResultTypeMismatchExpectedButFound,
  4201. [],DeclResult,ImplResult,ImplProc);
  4202. end;
  4203. // check argument names
  4204. DeclArgs:=DeclProc.ProcType.Args;
  4205. ImplArgs:=ImplProc.ProcType.Args;
  4206. for i:=0 to DeclArgs.Count-1 do
  4207. begin
  4208. DeclName:=TPasArgument(DeclArgs[i]).Name;
  4209. ImplName:=TPasArgument(ImplArgs[i]).Name;
  4210. if CompareText(DeclName,ImplName)<>0 then
  4211. RaiseMsg(20170216151738,nFunctionHeaderMismatchForwardVarName,
  4212. sFunctionHeaderMismatchForwardVarName,[DeclProc.Name,DeclName,ImplName],ImplProc);
  4213. end;
  4214. end;
  4215. procedure TPasResolver.ResolveImplBlock(Block: TPasImplBlock);
  4216. var
  4217. i: Integer;
  4218. begin
  4219. if Block=nil then exit;
  4220. for i:=0 to Block.Elements.Count-1 do
  4221. ResolveImplElement(TPasImplElement(Block.Elements[i]));
  4222. end;
  4223. procedure TPasResolver.ResolveImplElement(El: TPasImplElement);
  4224. var
  4225. C: TClass;
  4226. begin
  4227. //writeln('TPasResolver.ResolveImplElement ',GetObjName(El));
  4228. if El=nil then exit;
  4229. C:=El.ClassType;
  4230. if C=TPasImplBeginBlock then
  4231. ResolveImplBlock(TPasImplBeginBlock(El))
  4232. else if C=TPasImplAssign then
  4233. ResolveImplAssign(TPasImplAssign(El))
  4234. else if C=TPasImplSimple then
  4235. ResolveImplSimple(TPasImplSimple(El))
  4236. else if C=TPasImplBlock then
  4237. ResolveImplBlock(TPasImplBlock(El))
  4238. else if C=TPasImplRepeatUntil then
  4239. begin
  4240. ResolveImplBlock(TPasImplBlock(El));
  4241. ResolveStatementConditionExpr(TPasImplRepeatUntil(El).ConditionExpr);
  4242. end
  4243. else if C=TPasImplIfElse then
  4244. begin
  4245. ResolveStatementConditionExpr(TPasImplIfElse(El).ConditionExpr);
  4246. ResolveImplElement(TPasImplIfElse(El).IfBranch);
  4247. ResolveImplElement(TPasImplIfElse(El).ElseBranch);
  4248. end
  4249. else if C=TPasImplWhileDo then
  4250. begin
  4251. ResolveStatementConditionExpr(TPasImplWhileDo(El).ConditionExpr);
  4252. ResolveImplElement(TPasImplWhileDo(El).Body);
  4253. end
  4254. else if C=TPasImplCaseOf then
  4255. ResolveImplCaseOf(TPasImplCaseOf(El))
  4256. else if C=TPasImplLabelMark then
  4257. ResolveImplLabelMark(TPasImplLabelMark(El))
  4258. else if C=TPasImplForLoop then
  4259. ResolveImplForLoop(TPasImplForLoop(El))
  4260. else if C=TPasImplTry then
  4261. begin
  4262. ResolveImplBlock(TPasImplTry(El));
  4263. ResolveImplBlock(TPasImplTry(El).FinallyExcept);
  4264. ResolveImplBlock(TPasImplTry(El).ElseBranch);
  4265. end
  4266. else if C=TPasImplExceptOn then
  4267. // handled in FinishExceptOnStatement
  4268. else if C=TPasImplRaise then
  4269. ResolveImplRaise(TPasImplRaise(El))
  4270. else if C=TPasImplCommand then
  4271. begin
  4272. if TPasImplCommand(El).Command<>'' then
  4273. RaiseNotYetImplemented(20160922163442,El,'TPasResolver.ResolveImplElement');
  4274. end
  4275. else if C=TPasImplAsmStatement then
  4276. ResolveImplAsm(TPasImplAsmStatement(El))
  4277. else if C=TPasImplWithDo then
  4278. ResolveImplWithDo(TPasImplWithDo(El))
  4279. else
  4280. RaiseNotYetImplemented(20160922163445,El,'TPasResolver.ResolveImplElement');
  4281. end;
  4282. procedure TPasResolver.ResolveImplCaseOf(CaseOf: TPasImplCaseOf);
  4283. var
  4284. i, j: Integer;
  4285. El: TPasElement;
  4286. Stat: TPasImplCaseStatement;
  4287. CaseExprResolved, OfExprResolved: TPasResolverResult;
  4288. OfExpr: TPasExpr;
  4289. ok: Boolean;
  4290. begin
  4291. ResolveExpr(CaseOf.CaseExpr,rraRead);
  4292. ComputeElement(CaseOf.CaseExpr,CaseExprResolved,[rcSetReferenceFlags]);
  4293. ok:=false;
  4294. if (rrfReadable in CaseExprResolved.Flags) then
  4295. begin
  4296. if (CaseExprResolved.BaseType in (btAllInteger+btAllBooleans+btAllStringAndChars)) then
  4297. ok:=true
  4298. else if CaseExprResolved.BaseType=btContext then
  4299. begin
  4300. if CaseExprResolved.TypeEl.ClassType=TPasEnumType then
  4301. ok:=true;
  4302. end;
  4303. end;
  4304. if not ok then
  4305. RaiseXExpectedButYFound(20170216151952,'ordinal expression',
  4306. GetTypeDescription(CaseExprResolved.TypeEl),CaseOf.CaseExpr);
  4307. for i:=0 to CaseOf.Elements.Count-1 do
  4308. begin
  4309. El:=TPasElement(CaseOf.Elements[i]);
  4310. if El.ClassType=TPasImplCaseStatement then
  4311. begin
  4312. Stat:=TPasImplCaseStatement(El);
  4313. for j:=0 to Stat.Expressions.Count-1 do
  4314. begin
  4315. //writeln('TPasResolver.ResolveImplCaseOf Stat.Expr[',j,']=',GetObjName(El));
  4316. OfExpr:=TPasExpr(Stat.Expressions[j]);
  4317. ResolveExpr(OfExpr,rraRead);
  4318. ComputeElement(OfExpr,OfExprResolved,[rcConstant,rcSetReferenceFlags]);
  4319. if OfExprResolved.BaseType=btRange then
  4320. ConvertRangeToFirstValue(OfExprResolved);
  4321. CheckEqualResCompatibility(CaseExprResolved,OfExprResolved,OfExpr,true);
  4322. end;
  4323. ResolveImplElement(Stat.Body);
  4324. end
  4325. else if El.ClassType=TPasImplCaseElse then
  4326. ResolveImplBlock(TPasImplCaseElse(El))
  4327. else
  4328. RaiseNotYetImplemented(20160922163448,El);
  4329. end;
  4330. // Note: CaseOf.ElseBranch was already resolved via Elements
  4331. end;
  4332. procedure TPasResolver.ResolveImplLabelMark(Mark: TPasImplLabelMark);
  4333. begin
  4334. RaiseNotYetImplemented(20161014141636,Mark);
  4335. end;
  4336. procedure TPasResolver.ResolveImplForLoop(Loop: TPasImplForLoop);
  4337. var
  4338. VarResolved, StartResolved, EndResolved: TPasResolverResult;
  4339. begin
  4340. // loop var
  4341. ResolveExpr(Loop.VariableName,rraReadAndAssign);
  4342. ComputeElement(Loop.VariableName,VarResolved,[rcNoImplicitProc,rcSetReferenceFlags]);
  4343. if ResolvedElCanBeVarParam(VarResolved)
  4344. and ((VarResolved.BaseType in (btAllBooleans+btAllInteger+btAllChars))
  4345. or ((VarResolved.BaseType=btContext) and (VarResolved.TypeEl.ClassType=TPasEnumType))) then
  4346. else
  4347. RaiseMsg(20170216151955,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Loop.VariableName);
  4348. // start value
  4349. ResolveExpr(Loop.StartExpr,rraRead);
  4350. ComputeElement(Loop.StartExpr,StartResolved,[rcSetReferenceFlags]);
  4351. if CheckAssignResCompatibility(VarResolved,StartResolved,Loop.StartExpr,true)=cIncompatible then
  4352. RaiseIncompatibleTypeRes(20170216151958,nIncompatibleTypesGotExpected,
  4353. [],StartResolved,VarResolved,Loop.StartExpr);
  4354. // end value
  4355. ResolveExpr(Loop.EndExpr,rraRead);
  4356. ComputeElement(Loop.EndExpr,EndResolved,[rcSetReferenceFlags]);
  4357. if CheckAssignResCompatibility(VarResolved,EndResolved,Loop.EndExpr,false)=cIncompatible then
  4358. RaiseIncompatibleTypeRes(20170216152001,nIncompatibleTypesGotExpected,
  4359. [],EndResolved,VarResolved,Loop.EndExpr);
  4360. ResolveImplElement(Loop.Body);
  4361. end;
  4362. procedure TPasResolver.ResolveImplWithDo(El: TPasImplWithDo);
  4363. var
  4364. i, OldScopeCount: Integer;
  4365. Expr, ErrorEl: TPasExpr;
  4366. ExprResolved: TPasResolverResult;
  4367. TypeEl: TPasType;
  4368. WithScope: TPasWithScope;
  4369. WithExprScope: TPasWithExprScope;
  4370. ExprScope: TPasScope;
  4371. OnlyTypeMembers: Boolean;
  4372. ClassEl: TPasClassType;
  4373. begin
  4374. OldScopeCount:=ScopeCount;
  4375. WithScope:=TPasWithScope(CreateScope(El,TPasWithScope));
  4376. PushScope(WithScope);
  4377. for i:=0 to El.Expressions.Count-1 do
  4378. begin
  4379. Expr:=TPasExpr(El.Expressions[i]);
  4380. ResolveExpr(Expr,rraRead);
  4381. ComputeElement(Expr,ExprResolved,[rcSkipTypeAlias,rcSetReferenceFlags]);
  4382. {$IFDEF VerbosePasResolver}
  4383. writeln('TPasResolver.ResolveImplWithDo ExprResolved=',GetResolverResultDbg(ExprResolved));
  4384. {$ENDIF}
  4385. ErrorEl:=Expr;
  4386. TypeEl:=ExprResolved.TypeEl;
  4387. // ToDo: use last element in Expr for error position
  4388. if TypeEl=nil then
  4389. RaiseMsg(20170216152004,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
  4390. [BaseTypeNames[ExprResolved.BaseType]],ErrorEl);
  4391. OnlyTypeMembers:=false;
  4392. if TypeEl.ClassType=TPasRecordType then
  4393. begin
  4394. ExprScope:=TPasRecordType(TypeEl).CustomData as TPasRecordScope;
  4395. if ExprResolved.IdentEl is TPasType then
  4396. // e.g. with TPoint do PointInCircle
  4397. OnlyTypeMembers:=true;
  4398. end
  4399. else if TypeEl.ClassType=TPasClassType then
  4400. begin
  4401. ExprScope:=TPasClassType(TypeEl).CustomData as TPasClassScope;
  4402. if ExprResolved.IdentEl is TPasType then
  4403. // e.g. with TFPMemoryImage do FindHandlerFromExtension()
  4404. OnlyTypeMembers:=true;
  4405. end
  4406. else if TypeEl.ClassType=TPasClassOfType then
  4407. begin
  4408. // e.g. with ImageClass do FindHandlerFromExtension()
  4409. ClassEl:=ResolveAliasType(TPasClassOfType(TypeEl).DestType) as TPasClassType;
  4410. ExprScope:=ClassEl.CustomData as TPasClassScope;
  4411. OnlyTypeMembers:=true;
  4412. end
  4413. else
  4414. RaiseMsg(20170216152007,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
  4415. [TypeEl.ElementTypeName],ErrorEl);
  4416. WithExprScope:=ScopeClass_WithExpr.Create;
  4417. WithExprScope.WithScope:=WithScope;
  4418. WithExprScope.Index:=i;
  4419. WithExprScope.Expr:=Expr;
  4420. WithExprScope.Scope:=ExprScope;
  4421. if not (ExprResolved.IdentEl is TPasType) then
  4422. Include(WithExprScope.Flags,wesfNeedTmpVar);
  4423. if OnlyTypeMembers then
  4424. Include(WithExprScope.Flags,wesfOnlyTypeMembers);
  4425. if (not (rrfWritable in ExprResolved.Flags))
  4426. and (ExprResolved.BaseType=btContext)
  4427. and (ExprResolved.TypeEl.ClassType=TPasRecordType) then
  4428. Include(WithExprScope.Flags,wesfConstParent);
  4429. WithScope.ExpressionScopes.Add(WithExprScope);
  4430. PushScope(WithExprScope);
  4431. end;
  4432. ResolveImplElement(El.Body);
  4433. CheckTopScope(ScopeClass_WithExpr);
  4434. if TopScope<>WithScope.ExpressionScopes[WithScope.ExpressionScopes.Count-1] then
  4435. RaiseInternalError(20160923102846);
  4436. while ScopeCount>OldScopeCount do
  4437. PopScope;
  4438. end;
  4439. procedure TPasResolver.ResolveImplAsm(El: TPasImplAsmStatement);
  4440. begin
  4441. if El=nil then ;
  4442. end;
  4443. procedure TPasResolver.ResolveImplAssign(El: TPasImplAssign);
  4444. var
  4445. LeftResolved, RightResolved: TPasResolverResult;
  4446. Flags: TPasResolverComputeFlags;
  4447. Access: TResolvedRefAccess;
  4448. begin
  4449. if El.Kind=akDefault then
  4450. Access:=rraAssign
  4451. else
  4452. Access:=rraReadAndAssign;
  4453. ResolveExpr(El.left,Access);
  4454. ResolveExpr(El.right,rraRead);
  4455. {$IFDEF VerbosePasResolver}
  4456. writeln('TPasResolver.ResolveImplAssign Kind=',El.Kind,' left=',GetObjName(El.left),' right=',GetObjName(el.right));
  4457. {$ENDIF}
  4458. // check LHS can be assigned
  4459. ComputeElement(El.left,LeftResolved,[rcSkipTypeAlias,rcNoImplicitProc,rcSetReferenceFlags]);
  4460. CheckCanBeLHS(LeftResolved,true,El.left);
  4461. // compute RHS
  4462. Flags:=[rcSkipTypeAlias,rcSetReferenceFlags];
  4463. if IsProcedureType(LeftResolved,true) then
  4464. if (msDelphi in CurrentParser.CurrentModeswitches) then
  4465. Include(Flags,rcNoImplicitProc) // a proc type can use param less procs
  4466. else
  4467. Include(Flags,rcNoImplicitProcType); // a proc type can use a param less proc type
  4468. {$IFDEF VerbosePasResolver}
  4469. writeln('TPasResolver.ResolveImplAssign Left=',GetResolverResultDbg(LeftResolved),' Flags=',dbgs(Flags));
  4470. {$ENDIF}
  4471. ComputeElement(El.right,RightResolved,Flags);
  4472. {$IFDEF VerbosePasResolver}
  4473. writeln('TPasResolver.ResolveImplAssign Right=',GetResolverResultDbg(RightResolved));
  4474. {$ENDIF}
  4475. case El.Kind of
  4476. akDefault:
  4477. begin
  4478. CheckAssignResCompatibility(LeftResolved,RightResolved,El.right,true);
  4479. CheckAssignExprRange(LeftResolved,El.right);
  4480. end;
  4481. akAdd, akMinus,akMul,akDivision:
  4482. begin
  4483. if (El.Kind in [akAdd,akMinus,akMul]) and (LeftResolved.BaseType in btAllInteger) then
  4484. begin
  4485. if (not (rrfReadable in RightResolved.Flags))
  4486. or not (RightResolved.BaseType in btAllInteger) then
  4487. RaiseMsg(20170216152009,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  4488. [BaseTypes[RightResolved.BaseType],BaseTypes[LeftResolved.BaseType]],El.right);
  4489. end
  4490. else if (El.Kind=akAdd) and (LeftResolved.BaseType in btAllStrings) then
  4491. begin
  4492. if (not (rrfReadable in RightResolved.Flags))
  4493. or not (RightResolved.BaseType in btAllStringAndChars) then
  4494. RaiseMsg(20170216152012,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  4495. [BaseTypes[RightResolved.BaseType],BaseTypes[LeftResolved.BaseType]],El.right);
  4496. end
  4497. else if (El.Kind in [akAdd,akMinus,akMul,akDivision])
  4498. and (LeftResolved.BaseType in btAllFloats) then
  4499. begin
  4500. if (not (rrfReadable in RightResolved.Flags))
  4501. or not (RightResolved.BaseType in (btAllInteger+btAllFloats)) then
  4502. RaiseMsg(20170216152107,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  4503. [BaseTypes[RightResolved.BaseType],BaseTypes[LeftResolved.BaseType]],El.right);
  4504. end
  4505. else if (LeftResolved.BaseType=btSet) and (El.Kind in [akAdd,akMinus,akMul]) then
  4506. begin
  4507. if (not (rrfReadable in RightResolved.Flags))
  4508. or not (RightResolved.BaseType=btSet) then
  4509. RaiseMsg(20170216152110,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  4510. [BaseTypeNames[RightResolved.BaseType],'set of '+BaseTypeNames[LeftResolved.SubType]],El.right);
  4511. if (LeftResolved.SubType=RightResolved.SubType)
  4512. or ((LeftResolved.SubType in btAllInteger) and (RightResolved.SubType in btAllInteger))
  4513. or ((LeftResolved.SubType in btAllBooleans) and (RightResolved.SubType in btAllBooleans))
  4514. then
  4515. else
  4516. RaiseMsg(20170216152117,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  4517. ['set of '+BaseTypeNames[RightResolved.SubType],'set of '+BaseTypeNames[LeftResolved.SubType]],El.right);
  4518. end
  4519. else
  4520. RaiseMsg(20170216152125,nIllegalQualifier,sIllegalQualifier,[AssignKindNames[El.Kind]],El);
  4521. // store const expression result
  4522. Eval(El.right,[]);
  4523. end;
  4524. else
  4525. RaiseNotYetImplemented(20160927143649,El,'AssignKind '+AssignKindNames[El.Kind]);
  4526. end;
  4527. end;
  4528. procedure TPasResolver.ResolveImplSimple(El: TPasImplSimple);
  4529. var
  4530. ExprResolved: TPasResolverResult;
  4531. Expr: TPasExpr;
  4532. begin
  4533. Expr:=El.expr;
  4534. ResolveExpr(Expr,rraRead);
  4535. ComputeElement(Expr,ExprResolved,[rcSkipTypeAlias,rcSetReferenceFlags]);
  4536. if (rrfCanBeStatement in ExprResolved.Flags) then
  4537. exit;
  4538. {$IFDEF VerbosePasResolver}
  4539. writeln('TPasResolver.ResolveImplSimple El=',GetObjName(El),' El.Expr=',GetObjName(El.Expr),' ExprResolved=',GetResolverResultDbg(ExprResolved));
  4540. {$ENDIF}
  4541. RaiseMsg(20170216152127,nIllegalExpression,sIllegalExpression,[],El);
  4542. end;
  4543. procedure TPasResolver.ResolveImplRaise(El: TPasImplRaise);
  4544. var
  4545. ResolvedEl: TPasResolverResult;
  4546. begin
  4547. if El.ExceptObject<>nil then
  4548. begin
  4549. ResolveExpr(El.ExceptObject,rraRead);
  4550. ComputeElement(El.ExceptObject,ResolvedEl,[rcSkipTypeAlias,rcSetReferenceFlags]);
  4551. CheckIsClass(El.ExceptObject,ResolvedEl);
  4552. if ResolvedEl.IdentEl<>nil then
  4553. begin
  4554. if (ResolvedEl.IdentEl is TPasVariable)
  4555. or (ResolvedEl.IdentEl is TPasArgument) then
  4556. else
  4557. RaiseMsg(20170216152133,nXExpectedButYFound,sXExpectedButYFound,
  4558. ['variable',ResolvedEl.IdentEl.ElementTypeName],El.ExceptObject);
  4559. end
  4560. else if ResolvedEl.ExprEl<>nil then
  4561. else
  4562. RaiseMsg(201702303145230,nXExpectedButYFound,sXExpectedButYFound,
  4563. ['variable',GetResolverResultDbg(ResolvedEl)],El.ExceptObject);
  4564. if not (rrfReadable in ResolvedEl.Flags) then
  4565. RaiseMsg(20170303145037,nNotReadable,sNotReadable,[],El.ExceptObject);
  4566. end;
  4567. if El.ExceptAddr<>nil then
  4568. ResolveExpr(El.ExceptAddr,rraRead);
  4569. end;
  4570. procedure TPasResolver.ResolveExpr(El: TPasExpr; Access: TResolvedRefAccess);
  4571. var
  4572. Primitive: TPrimitiveExpr;
  4573. ElClass: TClass;
  4574. begin
  4575. {$IFDEF VerbosePasResolver}
  4576. writeln('TPasResolver.ResolveExpr ',GetObjName(El),' ',Access);
  4577. {$ENDIF}
  4578. if El=nil then
  4579. RaiseNotYetImplemented(20160922163453,El);
  4580. ElClass:=El.ClassType;
  4581. if ElClass=TPrimitiveExpr then
  4582. begin
  4583. Primitive:=TPrimitiveExpr(El);
  4584. case Primitive.Kind of
  4585. pekIdent: ResolveNameExpr(El,Primitive.Value,Access);
  4586. pekNumber: ;
  4587. pekString: ;
  4588. pekNil,pekBoolConst: ;
  4589. else
  4590. RaiseNotYetImplemented(20160922163451,El);
  4591. end;
  4592. end
  4593. else if ElClass=TUnaryExpr then
  4594. ResolveExpr(TUnaryExpr(El).Operand,Access)
  4595. else if ElClass=TBinaryExpr then
  4596. ResolveBinaryExpr(TBinaryExpr(El),Access)
  4597. else if ElClass=TParamsExpr then
  4598. ResolveParamsExpr(TParamsExpr(El),Access)
  4599. else if ElClass=TBoolConstExpr then
  4600. else if ElClass=TNilExpr then
  4601. else if ElClass=TSelfExpr then
  4602. ResolveNameExpr(El,'Self',Access)
  4603. else if ElClass=TInheritedExpr then
  4604. ResolveInherited(TInheritedExpr(El),Access)
  4605. else if ElClass=TArrayValues then
  4606. begin
  4607. if Access<>rraRead then
  4608. RaiseMsg(20170303205743,nVariableIdentifierExpected,sVariableIdentifierExpected,
  4609. [],El);
  4610. ResolveArrayValues(TArrayValues(El));
  4611. end
  4612. else
  4613. RaiseNotYetImplemented(20170222184329,El);
  4614. if El.format1<>nil then
  4615. ResolveExpr(El.format1,rraRead);
  4616. if El.format2<>nil then
  4617. ResolveExpr(El.format2,rraRead);
  4618. end;
  4619. procedure TPasResolver.ResolveStatementConditionExpr(El: TPasExpr);
  4620. var
  4621. ResolvedCond: TPasResolverResult;
  4622. begin
  4623. ResolveExpr(El,rraRead);
  4624. ComputeElement(El,ResolvedCond,[rcSkipTypeAlias,rcSetReferenceFlags]);
  4625. CheckConditionExpr(El,ResolvedCond);
  4626. end;
  4627. procedure TPasResolver.ResolveNameExpr(El: TPasExpr; const aName: string;
  4628. Access: TResolvedRefAccess);
  4629. var
  4630. FindData: TPRFindData;
  4631. DeclEl: TPasElement;
  4632. Proc: TPasProcedure;
  4633. Ref: TResolvedReference;
  4634. BuiltInProc: TResElDataBuiltInProc;
  4635. p: SizeInt;
  4636. DottedName: String;
  4637. Bin: TBinaryExpr;
  4638. begin
  4639. {$IFDEF VerbosePasResolver}
  4640. writeln('TPasResolver.ResolveNameExpr El=',GetObjName(El),' Name="',aName,'" ',Access);
  4641. {$ENDIF}
  4642. DeclEl:=FindElementWithoutParams(aName,FindData,El,false);
  4643. if DeclEl.ClassType=TPasUsesUnit then
  4644. begin
  4645. // the first name of a unit matches -> find unit with longest match
  4646. FindLongestUnitName(DeclEl,El);
  4647. FindData.Found:=DeclEl;
  4648. end;
  4649. Ref:=CreateReference(DeclEl,El,Access,@FindData);
  4650. CheckFoundElement(FindData,Ref);
  4651. if DeclEl is TPasProcedure then
  4652. begin
  4653. // identifier is a proc and args brackets are missing
  4654. if El.Parent.ClassType=TPasProperty then
  4655. // a property accessor does not need args -> ok
  4656. else
  4657. begin
  4658. // examples: funca or @proca or a.funca or @a.funca ...
  4659. Proc:=TPasProcedure(DeclEl);
  4660. if ProcNeedsParams(Proc.ProcType) and not ExprIsAddrTarget(El) then
  4661. begin
  4662. {$IFDEF VerbosePasResolver}
  4663. writeln('TPasResolver.ResolveNameExpr ',GetObjName(El));
  4664. {$ENDIF}
  4665. RaiseMsg(20170216152138,nWrongNumberOfParametersForCallTo,
  4666. sWrongNumberOfParametersForCallTo,[Proc.Name],El);
  4667. end;
  4668. end;
  4669. end
  4670. else if DeclEl.ClassType=TPasUnresolvedSymbolRef then
  4671. begin
  4672. if DeclEl.CustomData is TResElDataBuiltInProc then
  4673. begin
  4674. BuiltInProc:=TResElDataBuiltInProc(DeclEl.CustomData);
  4675. BuiltInProc.GetCallCompatibility(BuiltInProc,El,true);
  4676. end;
  4677. end
  4678. else if (DeclEl.ClassType=TPasUsesUnit) or (DeclEl is TPasModule) then
  4679. begin
  4680. // unit reference
  4681. // dotted unit names needs a ref for each expression identifier
  4682. // Note: El is the first TPrimitiveExpr of the dotted unit name reference
  4683. DottedName:=DeclEl.Name;
  4684. repeat
  4685. p:=Pos('.',DottedName);
  4686. if p<1 then break;
  4687. Delete(DottedName,1,p);
  4688. El:=GetNextDottedExpr(El);
  4689. if El=nil then
  4690. RaiseInternalError(20170503002012);
  4691. CreateReference(DeclEl,El,Access);
  4692. if (El.Parent is TBinaryExpr) and (TBinaryExpr(El.Parent).right=El) then
  4693. begin
  4694. Bin:=TBinaryExpr(El.Parent);
  4695. while Bin.OpCode=eopSubIdent do
  4696. begin
  4697. CreateReference(DeclEl,Bin,Access);
  4698. if not (Bin.Parent is TBinaryExpr) then break;
  4699. if (TBinaryExpr(Bin.Parent).right<>Bin) then break;
  4700. Bin:=TBinaryExpr(Bin.Parent);
  4701. end;
  4702. end;
  4703. until false;
  4704. end;
  4705. end;
  4706. procedure TPasResolver.ResolveInherited(El: TInheritedExpr;
  4707. Access: TResolvedRefAccess);
  4708. var
  4709. ProcScope, DeclProcScope, SelfScope: TPasProcedureScope;
  4710. AncestorScope, ClassScope: TPasClassScope;
  4711. DeclProc, AncestorProc: TPasProcedure;
  4712. begin
  4713. {$IFDEF VerbosePasResolver}
  4714. writeln('TPasResolver.ResolveInherited El.Parent=',GetTreeDbg(El.Parent));
  4715. {$ENDIF}
  4716. if (El.Parent.ClassType=TBinaryExpr)
  4717. and (TBinaryExpr(El.Parent).OpCode=eopNone) then
  4718. begin
  4719. // e.g. 'inherited Proc;'
  4720. ResolveInheritedCall(TBinaryExpr(El.Parent),Access);
  4721. exit;
  4722. end;
  4723. // 'inherited;' without expression
  4724. CheckTopScope(TPasProcedureScope);
  4725. ProcScope:=TPasProcedureScope(TopScope);
  4726. SelfScope:=ProcScope.GetSelfScope;
  4727. if SelfScope=nil then
  4728. RaiseMsg(20170216152141,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
  4729. ClassScope:=SelfScope.ClassScope;
  4730. AncestorScope:=ClassScope.AncestorScope;
  4731. if AncestorScope=nil then
  4732. begin
  4733. // 'inherited;' without ancestor class is silently ignored
  4734. exit;
  4735. end;
  4736. // search ancestor in element, i.e. 'inherited' expression
  4737. DeclProc:=SelfScope.DeclarationProc;
  4738. DeclProcScope:=DeclProc.CustomData as TPasProcedureScope;
  4739. AncestorProc:=DeclProcScope.OverriddenProc;
  4740. if AncestorProc<>nil then
  4741. begin
  4742. CreateReference(AncestorProc,El,Access);
  4743. if AncestorProc.IsAbstract then
  4744. RaiseMsg(20170216152144,nAbstractMethodsCannotBeCalledDirectly,
  4745. sAbstractMethodsCannotBeCalledDirectly,[],El);
  4746. end
  4747. else
  4748. begin
  4749. // 'inherited;' without ancestor method is silently ignored
  4750. exit;
  4751. end;
  4752. end;
  4753. procedure TPasResolver.ResolveInheritedCall(El: TBinaryExpr;
  4754. Access: TResolvedRefAccess);
  4755. // El.OpCode=eopNone
  4756. // El.left is TInheritedExpr
  4757. // El.right is the identifier and parameters
  4758. var
  4759. ProcScope, SelfScope: TPasProcedureScope;
  4760. AncestorScope, ClassScope: TPasClassScope;
  4761. AncestorClass: TPasClassType;
  4762. InhScope: TPasDotClassScope;
  4763. begin
  4764. {$IFDEF VerbosePasResolver}
  4765. writeln('TPasResolver.ResolveInheritedCall El=',GetTreeDbg(El));
  4766. {$ENDIF}
  4767. CheckTopScope(TPasProcedureScope);
  4768. ProcScope:=TPasProcedureScope(TopScope);
  4769. SelfScope:=ProcScope.GetSelfScope;
  4770. if SelfScope=nil then
  4771. RaiseMsg(20170216152148,nInheritedOnlyWorksInMethods,sInheritedOnlyWorksInMethods,[],El);
  4772. ClassScope:=SelfScope.ClassScope;
  4773. AncestorScope:=ClassScope.AncestorScope;
  4774. if AncestorScope=nil then
  4775. RaiseMsg(20170216152151,nInheritedNeedsAncestor,sInheritedNeedsAncestor,[],El.left);
  4776. // search call in ancestor
  4777. AncestorClass:=TPasClassType(AncestorScope.Element);
  4778. InhScope:=PushClassDotScope(AncestorClass);
  4779. InhScope.InheritedExpr:=true;
  4780. ResolveExpr(El.right,Access);
  4781. PopScope;
  4782. end;
  4783. procedure TPasResolver.ResolveBinaryExpr(El: TBinaryExpr;
  4784. Access: TResolvedRefAccess);
  4785. begin
  4786. {$IFDEF VerbosePasResolver}
  4787. //writeln('TPasResolver.ResolveBinaryExpr left=',GetObjName(El.left),' right=',GetObjName(El.right),' opcode=',OpcodeStrings[El.OpCode]);
  4788. {$ENDIF}
  4789. ResolveExpr(El.left,rraRead);
  4790. if El.right=nil then exit;
  4791. case El.OpCode of
  4792. eopNone:
  4793. case El.Kind of
  4794. pekRange:
  4795. ResolveExpr(El.right,rraRead);
  4796. else
  4797. if El.left.ClassType=TInheritedExpr then
  4798. else
  4799. begin
  4800. {$IFDEF VerbosePasResolver}
  4801. writeln('TPasResolver.ResolveBinaryExpr El.Kind=',ExprKindNames[El.Kind],' El.Left=',GetObjName(El.left),' El.Right=',GetObjName(El.right),' parent=',GetObjName(El.Parent));
  4802. {$ENDIF}
  4803. RaiseNotYetImplemented(20160922163456,El);
  4804. end;
  4805. end;
  4806. eopAdd,
  4807. eopSubtract,
  4808. eopMultiply,
  4809. eopDivide,
  4810. eopDiv,
  4811. eopMod,
  4812. eopPower,
  4813. eopShr,
  4814. eopShl,
  4815. eopNot,
  4816. eopAnd,
  4817. eopOr,
  4818. eopXor,
  4819. eopEqual,
  4820. eopNotEqual,
  4821. eopLessThan,
  4822. eopGreaterThan,
  4823. eopLessthanEqual,
  4824. eopGreaterThanEqual,
  4825. eopIn,
  4826. eopIs,
  4827. eopAs,
  4828. eopSymmetricaldifference:
  4829. ResolveExpr(El.right,rraRead);
  4830. eopSubIdent:
  4831. ResolveSubIdent(El,Access);
  4832. else
  4833. RaiseNotYetImplemented(20160922163459,El,OpcodeStrings[El.OpCode]);
  4834. end;
  4835. end;
  4836. procedure TPasResolver.ResolveSubIdent(El: TBinaryExpr;
  4837. Access: TResolvedRefAccess);
  4838. var
  4839. aModule: TPasModule;
  4840. ClassEl: TPasClassType;
  4841. ClassScope: TPasDotClassScope;
  4842. LeftResolved: TPasResolverResult;
  4843. Left: TPasExpr;
  4844. RecordEl: TPasRecordType;
  4845. RecordScope: TPasDotRecordScope;
  4846. begin
  4847. if El.CustomData is TResolvedReference then
  4848. exit; // for example, when a.b has a dotted unit name
  4849. Left:=El.left;
  4850. //writeln('TPasResolver.ResolveSubIdent Left=',GetObjName(Left));
  4851. ComputeElement(Left,LeftResolved,[rcSetReferenceFlags]);
  4852. if LeftResolved.BaseType=btModule then
  4853. begin
  4854. // e.g. unitname.identifier
  4855. // => search in interface and if this is our module in the implementation
  4856. aModule:=LeftResolved.IdentEl as TPasModule;
  4857. PushModuleDotScope(aModule);
  4858. ResolveExpr(El.right,Access);
  4859. PopScope;
  4860. exit;
  4861. end
  4862. else if LeftResolved.TypeEl=nil then
  4863. begin
  4864. // illegal qualifier, see below
  4865. end
  4866. else if LeftResolved.TypeEl.ClassType=TPasClassType then
  4867. begin
  4868. ClassEl:=TPasClassType(LeftResolved.TypeEl);
  4869. ClassScope:=PushClassDotScope(ClassEl);
  4870. if LeftResolved.IdentEl is TPasType then
  4871. // e.g. TFPMemoryImage.FindHandlerFromExtension()
  4872. ClassScope.OnlyTypeMembers:=true
  4873. else
  4874. // e.g. Image.Width
  4875. ClassScope.OnlyTypeMembers:=false;
  4876. ResolveExpr(El.right,Access);
  4877. PopScope;
  4878. exit;
  4879. end
  4880. else if LeftResolved.TypeEl.ClassType=TPasClassOfType then
  4881. begin
  4882. // e.g. ImageClass.FindHandlerFromExtension()
  4883. ClassEl:=ResolveAliasType(TPasClassOfType(LeftResolved.TypeEl).DestType) as TPasClassType;
  4884. ClassScope:=PushClassDotScope(ClassEl);
  4885. ClassScope.OnlyTypeMembers:=true;
  4886. ResolveExpr(El.right,Access);
  4887. PopScope;
  4888. exit;
  4889. end
  4890. else if LeftResolved.TypeEl.ClassType=TPasRecordType then
  4891. begin
  4892. RecordEl:=TPasRecordType(LeftResolved.TypeEl);
  4893. RecordScope:=PushRecordDotScope(RecordEl);
  4894. RecordScope.ConstParent:=not (rrfWritable in LeftResolved.Flags);
  4895. if LeftResolved.IdentEl is TPasType then
  4896. // e.g. TPoint.PointInCircle
  4897. RecordScope.OnlyTypeMembers:=true
  4898. else
  4899. begin
  4900. // e.g. aPoint.X
  4901. AccessExpr(El.left,Access);
  4902. RecordScope.OnlyTypeMembers:=false;
  4903. end;
  4904. ResolveExpr(El.right,Access);
  4905. PopScope;
  4906. exit;
  4907. end
  4908. else if LeftResolved.TypeEl.ClassType=TPasEnumType then
  4909. begin
  4910. if LeftResolved.IdentEl is TPasType then
  4911. begin
  4912. // e.g. TShiftState.ssAlt
  4913. PushEnumDotScope(TPasEnumType(LeftResolved.TypeEl));
  4914. ResolveExpr(El.right,Access);
  4915. PopScope;
  4916. exit;
  4917. end;
  4918. end
  4919. else
  4920. RaiseMsg(20170216152541,nExprTypeMustBeClassOrRecordTypeGot,sExprTypeMustBeClassOrRecordTypeGot,
  4921. [LeftResolved.TypeEl.ElementTypeName],El);
  4922. {$IFDEF VerbosePasResolver}
  4923. writeln('TPasResolver.ResolveSubIdent left=',GetObjName(Left),' right=',GetObjName(El.right),' leftresolved=',GetResolverResultDbg(LeftResolved));
  4924. {$ENDIF}
  4925. RaiseMsg(20170216152157,nIllegalQualifier,sIllegalQualifier,['.'],El);
  4926. end;
  4927. procedure TPasResolver.ResolveParamsExpr(Params: TParamsExpr;
  4928. Access: TResolvedRefAccess);
  4929. var
  4930. i, ScopeDepth: Integer;
  4931. ParamAccess: TResolvedRefAccess;
  4932. begin
  4933. if (Params.Kind=pekSet) and not (Access in [rraRead,rraParamToUnknownProc]) then
  4934. begin
  4935. {$IFDEF VerbosePasResolver}
  4936. writeln('TPasResolver.ResolveParamsExpr SET literal Access=',Access);
  4937. {$ENDIF}
  4938. RaiseMsg(20170303211052,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Params);
  4939. end;
  4940. // first resolve params
  4941. ResetSubScopes(ScopeDepth);
  4942. if Params.Kind in [pekFuncParams,pekArrayParams] then
  4943. ParamAccess:=rraParamToUnknownProc
  4944. else
  4945. ParamAccess:=rraRead;
  4946. for i:=0 to length(Params.Params)-1 do
  4947. ResolveExpr(Params.Params[i],ParamAccess);
  4948. RestoreSubScopes(ScopeDepth);
  4949. // then resolve the call, typecast, array, set
  4950. if (Params.Kind=pekFuncParams) then
  4951. ResolveFuncParamsExpr(Params,Access)
  4952. else if (Params.Kind=pekArrayParams) then
  4953. ResolveArrayParamsExpr(Params,Access)
  4954. else if (Params.Kind=pekSet) then
  4955. ResolveSetParamsExpr(Params)
  4956. else
  4957. RaiseNotYetImplemented(20160922163501,Params);
  4958. end;
  4959. procedure TPasResolver.ResolveFuncParamsExpr(Params: TParamsExpr;
  4960. Access: TResolvedRefAccess);
  4961. procedure FinishProcParams(ProcType: TPasProcedureType);
  4962. var
  4963. ParamAccess: TResolvedRefAccess;
  4964. i: Integer;
  4965. begin
  4966. if not (Access in [rraRead,rraParamToUnknownProc]) then
  4967. begin
  4968. {$IFDEF VerbosePasResolver}
  4969. writeln('TPasResolver.ResolveFuncParamsExpr.FinishProcParams Params=',GetObjName(Params),' Value=',GetObjName(Params.Value),' Access=',Access);
  4970. {$ENDIF}
  4971. RaiseMsg(20170306104440,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Params);
  4972. end;
  4973. for i:=0 to length(Params.Params)-1 do
  4974. begin
  4975. ParamAccess:=rraRead;
  4976. if i<ProcType.Args.Count then
  4977. case TPasArgument(ProcType.Args[i]).Access of
  4978. argVar: ParamAccess:=rraVarParam;
  4979. argOut: ParamAccess:=rraOutParam;
  4980. end;
  4981. AccessExpr(Params.Params[i],ParamAccess);
  4982. CheckCallProcCompatibility(ProcType,Params,false,true);
  4983. end;
  4984. end;
  4985. procedure FinishUntypedParams(ParamAccess: TResolvedRefAccess);
  4986. var
  4987. i: Integer;
  4988. Value: TPasExpr;
  4989. ResolvedEl: TPasResolverResult;
  4990. begin
  4991. for i:=0 to length(Params.Params)-1 do
  4992. begin
  4993. Value:=Params.Params[i];
  4994. AccessExpr(Value,ParamAccess);
  4995. ComputeElement(Value,ResolvedEl,[rcNoImplicitProcType,rcSetReferenceFlags]);
  4996. end;
  4997. end;
  4998. var
  4999. i: Integer;
  5000. ElName, Msg: String;
  5001. FindCallData: TFindCallElData;
  5002. Abort: boolean;
  5003. El, FoundEl: TPasElement;
  5004. Ref: TResolvedReference;
  5005. FindData: TPRFindData;
  5006. BuiltInProc: TResElDataBuiltInProc;
  5007. SubParams: TParamsExpr;
  5008. ResolvedEl: TPasResolverResult;
  5009. Value: TPasExpr;
  5010. TypeEl: TPasType;
  5011. C: TClass;
  5012. begin
  5013. Value:=Params.Value;
  5014. if IsNameExpr(Value) then
  5015. begin
  5016. // e.g. Name() -> find compatible
  5017. if Value.ClassType=TPrimitiveExpr then
  5018. ElName:=TPrimitiveExpr(Value).Value
  5019. else
  5020. ElName:='Self';
  5021. FindCallData:=Default(TFindCallElData);
  5022. FindCallData.Params:=Params;
  5023. Abort:=false;
  5024. IterateElements(ElName,@OnFindCallElements,@FindCallData,Abort);
  5025. if FindCallData.Found=nil then
  5026. RaiseIdentifierNotFound(20170216152544,ElName,Value);
  5027. if FindCallData.Distance=cIncompatible then
  5028. begin
  5029. // FoundEl one element, but it was incompatible => raise error
  5030. {$IFDEF VerbosePasResolver}
  5031. writeln('TPasResolver.ResolveFuncParamsExpr found one element, but it was incompatible => check again to raise error. Found=',GetObjName(FindCallData.Found));
  5032. WriteScopes;
  5033. {$ENDIF}
  5034. if FindCallData.Found is TPasProcedure then
  5035. CheckCallProcCompatibility(TPasProcedure(FindCallData.Found).ProcType,Params,true)
  5036. else if FindCallData.Found is TPasProcedureType then
  5037. CheckTypeCast(TPasProcedureType(FindCallData.Found),Params,true)
  5038. else if FindCallData.Found.ClassType=TPasUnresolvedSymbolRef then
  5039. begin
  5040. if FindCallData.Found.CustomData is TResElDataBuiltInProc then
  5041. begin
  5042. BuiltInProc:=TResElDataBuiltInProc(FindCallData.Found.CustomData);
  5043. BuiltInProc.GetCallCompatibility(BuiltInProc,Params,true);
  5044. end
  5045. else if FindCallData.Found.CustomData is TResElDataBaseType then
  5046. CheckTypeCast(TPasUnresolvedSymbolRef(FindCallData.Found),Params,true)
  5047. else
  5048. RaiseNotYetImplemented(20161006132825,FindCallData.Found);
  5049. end
  5050. else if FindCallData.Found is TPasType then
  5051. // Note: check TPasType after TPasUnresolvedSymbolRef
  5052. CheckTypeCast(TPasType(FindCallData.Found),Params,true)
  5053. else if FindCallData.Found is TPasVariable then
  5054. begin
  5055. TypeEl:=ResolveAliasType(TPasVariable(FindCallData.Found).VarType);
  5056. if TypeEl is TPasProcedureType then
  5057. CheckCallProcCompatibility(TPasProcedureType(TypeEl),Params,true)
  5058. else
  5059. RaiseMsg(20170405003522,nIllegalQualifier,sIllegalQualifier,['('],Params);
  5060. end
  5061. else
  5062. RaiseNotYetImplemented(20161003134755,FindCallData.Found);
  5063. end;
  5064. if FindCallData.Count>1 then
  5065. begin
  5066. // multiple overloads fit => search again and list the candidates
  5067. FindCallData:=Default(TFindCallElData);
  5068. FindCallData.Params:=Params;
  5069. FindCallData.List:=TFPList.Create;
  5070. try
  5071. IterateElements(ElName,@OnFindCallElements,@FindCallData,Abort);
  5072. Msg:='';
  5073. for i:=0 to FindCallData.List.Count-1 do
  5074. begin
  5075. El:=TPasElement(FindCallData.List[i]);
  5076. {$IFDEF VerbosePasResolver}
  5077. writeln('TPasResolver.ResolveFuncParamsExpr Overload Candidate: ',GetElementSourcePosStr(El),' ',GetTreeDbg(El));
  5078. {$ENDIF}
  5079. // emit a hint for each candidate
  5080. if El is TPasProcedure then
  5081. LogMsg(20170417180320,mtHint,nFoundCallCandidateX,sFoundCallCandidateX,
  5082. [GetProcTypeDescription(TPasProcedure(El).ProcType,true,true)],El);
  5083. Msg:=Msg+', '+GetElementSourcePosStr(El);
  5084. end;
  5085. RaiseMsg(20170216152200,nCantDetermineWhichOverloadedFunctionToCall,
  5086. sCantDetermineWhichOverloadedFunctionToCall+Msg,[ElName],Value);
  5087. finally
  5088. FindCallData.List.Free;
  5089. end;
  5090. end;
  5091. // FoundEl compatible element -> create reference
  5092. FoundEl:=FindCallData.Found;
  5093. Ref:=CreateReference(FoundEl,Value,rraRead);
  5094. if FindCallData.StartScope.ClassType=ScopeClass_WithExpr then
  5095. Ref.WithExprScope:=TPasWithExprScope(FindCallData.StartScope);
  5096. FindData:=Default(TPRFindData);
  5097. FindData.ErrorPosEl:=Value;
  5098. FindData.StartScope:=FindCallData.StartScope;
  5099. FindData.ElScope:=FindCallData.ElScope;
  5100. FindData.Found:=FoundEl;
  5101. CheckFoundElement(FindData,Ref);
  5102. // set param expression Access flags
  5103. if FoundEl is TPasProcedure then
  5104. // call proc
  5105. FinishProcParams(TPasProcedure(FoundEl).ProcType)
  5106. else if FoundEl is TPasType then
  5107. begin
  5108. TypeEl:=ResolveAliasType(TPasType(FoundEl));
  5109. C:=TypeEl.ClassType;
  5110. if (C=TPasClassType)
  5111. or (C=TPasClassOfType)
  5112. or (C=TPasRecordType)
  5113. or (C=TPasEnumType)
  5114. or (C=TPasSetType)
  5115. or (C=TPasPointerType)
  5116. or (C=TPasProcedureType)
  5117. or (C=TPasFunctionType)
  5118. or (C=TPasArrayType) then
  5119. begin
  5120. // type cast
  5121. FinishUntypedParams(Access);
  5122. end
  5123. else if C=TPasUnresolvedSymbolRef then
  5124. begin
  5125. if TypeEl.CustomData is TResElDataBuiltInProc then
  5126. begin
  5127. // call built-in proc
  5128. BuiltInProc:=TResElDataBuiltInProc(TypeEl.CustomData);
  5129. if Assigned(BuiltInProc.FinishParamsExpression) then
  5130. BuiltInProc.FinishParamsExpression(BuiltInProc,Params)
  5131. else
  5132. FinishUntypedParams(rraRead);
  5133. end
  5134. else if TypeEl.CustomData is TResElDataBaseType then
  5135. begin
  5136. // type cast to base type
  5137. FinishUntypedParams(Access);
  5138. end
  5139. else
  5140. begin
  5141. {$IFDEF VerbosePasResolver}
  5142. writeln('TPasResolver.ResolveFuncParamsExpr FoundEl=',GetObjName(FoundEl),' CustomData=',GetObjName(FoundEl.CustomData));
  5143. {$ENDIF}
  5144. RaiseNotYetImplemented(20170325145720,Params);
  5145. end;
  5146. end
  5147. else
  5148. begin
  5149. {$IFDEF VerbosePasResolver}
  5150. writeln('TPasResolver.ResolveFuncParamsExpr FoundEl=',GetObjName(FoundEl),' CustomData=',GetObjName(FoundEl.CustomData));
  5151. {$ENDIF}
  5152. RaiseMsg(20170306121908,nIllegalQualifier,sIllegalQualifier,['('],Params);
  5153. end;
  5154. end
  5155. else
  5156. begin
  5157. // FoundEl is not a type, maybe a var
  5158. ComputeElement(FoundEl,ResolvedEl,[rcNoImplicitProc,rcSetReferenceFlags]);
  5159. if ResolvedEl.TypeEl is TPasProcedureType then
  5160. begin
  5161. FinishProcParams(TPasProcedureType(ResolvedEl.TypeEl));
  5162. exit;
  5163. end;
  5164. {$IFDEF VerbosePasResolver}
  5165. writeln('TPasResolver.ResolveFuncParamsExpr FoundEl=',GetObjName(FoundEl),' CustomData=',GetObjName(FoundEl.CustomData),' Resolvedel=',GetResolverResultDbg(ResolvedEl));
  5166. {$ENDIF}
  5167. RaiseMsg(20170306104301,nIllegalQualifier,sIllegalQualifier,['('],Params);
  5168. end;
  5169. end
  5170. else if Value.ClassType=TParamsExpr then
  5171. begin
  5172. SubParams:=TParamsExpr(Value);
  5173. if (SubParams.Kind in [pekArrayParams,pekFuncParams]) then
  5174. begin
  5175. // e.g. Name()() or Name[]()
  5176. ResolveExpr(SubParams,rraRead);
  5177. ComputeElement(SubParams,ResolvedEl,[rcNoImplicitProc,rcSetReferenceFlags]);
  5178. if IsProcedureType(ResolvedEl,true) then
  5179. begin
  5180. CheckCallProcCompatibility(TPasProcedureType(ResolvedEl.TypeEl),Params,true);
  5181. CreateReference(TPasProcedureType(ResolvedEl.TypeEl),Value,Access);
  5182. exit;
  5183. end
  5184. end;
  5185. RaiseMsg(20170216152202,nIllegalQualifier,sIllegalQualifier,['('],Params);
  5186. end
  5187. else
  5188. RaiseNotYetImplemented(20161014085118,Params.Value);
  5189. end;
  5190. procedure TPasResolver.ResolveArrayParamsExpr(Params: TParamsExpr;
  5191. Access: TResolvedRefAccess);
  5192. var
  5193. ResolvedEl: TPasResolverResult;
  5194. procedure ResolveValueName(Value: TPasElement; ArrayName: string);
  5195. var
  5196. FindData: TPRFindData;
  5197. Ref: TResolvedReference;
  5198. DeclEl: TPasElement;
  5199. begin
  5200. // e.g. Name[]
  5201. DeclEl:=FindElementWithoutParams(ArrayName,FindData,Value,true);
  5202. Ref:=CreateReference(DeclEl,Value,Access,@FindData);
  5203. CheckFoundElement(FindData,Ref);
  5204. ComputeElement(Value,ResolvedEl,[rcSkipTypeAlias,rcSetReferenceFlags]);
  5205. end;
  5206. var
  5207. Value: TPasExpr;
  5208. SubParams: TParamsExpr;
  5209. begin
  5210. Value:=Params.Value;
  5211. if (Value.ClassType=TPrimitiveExpr)
  5212. and (TPrimitiveExpr(Value).Kind=pekIdent) then
  5213. // e.g. Name[]
  5214. ResolveValueName(Value,TPrimitiveExpr(Value).Value)
  5215. else if (Value.ClassType=TSelfExpr) then
  5216. // e.g. Self[]
  5217. ResolveValueName(Value,'Self')
  5218. else if Value.ClassType=TParamsExpr then
  5219. begin
  5220. SubParams:=TParamsExpr(Value);
  5221. if (SubParams.Kind in [pekArrayParams,pekFuncParams]) then
  5222. begin
  5223. // e.g. Name()[] or Name[][]
  5224. ResolveExpr(SubParams,rraRead);
  5225. ComputeElement(SubParams,ResolvedEl,[rcSkipTypeAlias,rcNoImplicitProc,rcSetReferenceFlags]);
  5226. if Value.CustomData=nil then
  5227. CreateReference(ResolvedEl.TypeEl,Value,Access);
  5228. end
  5229. else
  5230. RaiseNotYetImplemented(20161010194925,Value);
  5231. end
  5232. else
  5233. RaiseNotYetImplemented(20160927212610,Value);
  5234. {$IFDEF VerbosePasResolver}
  5235. writeln('TPasResolver.ResolveArrayParamsExpr Value=',GetObjName(Value),' ',GetResolverResultDbg(ResolvedEl));
  5236. {$ENDIF}
  5237. ResolveArrayParamsArgs(Params,ResolvedEl,Access);
  5238. end;
  5239. procedure TPasResolver.ResolveArrayParamsArgs(Params: TParamsExpr;
  5240. const ResolvedValue: TPasResolverResult; Access: TResolvedRefAccess);
  5241. var
  5242. ArgExp: TPasExpr;
  5243. ResolvedArg: TPasResolverResult;
  5244. PropEl: TPasProperty;
  5245. ClassScope: TPasClassScope;
  5246. i: Integer;
  5247. begin
  5248. if ResolvedValue.BaseType in btAllStrings then
  5249. begin
  5250. // string -> check that ResolvedValue is not merely a type, but has a value
  5251. if not (rrfReadable in ResolvedValue.Flags) then
  5252. RaiseXExpectedButYFound(20170216152548,'variable',ResolvedValue.TypeEl.ElementTypeName,Params);
  5253. // check single argument
  5254. if length(Params.Params)<1 then
  5255. RaiseMsg(20170216152204,nMissingParameterX,
  5256. sMissingParameterX,['character index'],Params)
  5257. else if length(Params.Params)>1 then
  5258. RaiseMsg(20170216152551,nIllegalQualifier,sIllegalQualifier,[','],Params.Params[1]);
  5259. // check argument is integer
  5260. ArgExp:=Params.Params[0];
  5261. ComputeElement(ArgExp,ResolvedArg,[rcSkipTypeAlias,rcSetReferenceFlags]);
  5262. if not (ResolvedArg.BaseType in btAllInteger) then
  5263. RaiseMsg(20170216152209,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  5264. [BaseTypeNames[ResolvedArg.BaseType],'integer'],ArgExp);
  5265. if not (rrfReadable in ResolvedArg.Flags) then
  5266. RaiseMsg(20170216152211,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  5267. ['type','value'],ArgExp);
  5268. AccessExpr(ArgExp,rraRead);
  5269. exit;
  5270. end
  5271. else if (ResolvedValue.IdentEl is TPasProperty)
  5272. and (TPasProperty(ResolvedValue.IdentEl).Args.Count>0) then
  5273. begin
  5274. PropEl:=TPasProperty(ResolvedValue.IdentEl);
  5275. CheckCallPropertyCompatibility(PropEl,Params,true);
  5276. FinishPropertyParamAccess(Params,PropEl);
  5277. exit;
  5278. end
  5279. else if ResolvedValue.BaseType=btContext then
  5280. begin
  5281. if ResolvedValue.TypeEl.ClassType=TPasClassType then
  5282. begin
  5283. ClassScope:=ResolvedValue.TypeEl.CustomData as TPasClassScope;
  5284. if ResolveBracketOperatorClass(Params,ResolvedValue,ClassScope,Access) then
  5285. exit;
  5286. end
  5287. else if ResolvedValue.TypeEl.ClassType=TPasArrayType then
  5288. begin
  5289. if ResolvedValue.IdentEl is TPasType then
  5290. RaiseMsg(20170216152215,nIllegalQualifier,sIllegalQualifier,['['],Params);
  5291. CheckCallArrayCompatibility(TPasArrayType(ResolvedValue.TypeEl),Params,true,true);
  5292. for i:=0 to length(Params.Params)-1 do
  5293. AccessExpr(Params.Params[i],rraRead);
  5294. exit;
  5295. end;
  5296. end;
  5297. RaiseMsg(20170216152217,nIllegalQualifier,sIllegalQualifier,['['],Params);
  5298. end;
  5299. function TPasResolver.ResolveBracketOperatorClass(Params: TParamsExpr;
  5300. const ResolvedValue: TPasResolverResult; ClassScope: TPasClassScope;
  5301. Access: TResolvedRefAccess): boolean;
  5302. var
  5303. PropEl: TPasProperty;
  5304. Value: TPasExpr;
  5305. begin
  5306. PropEl:=ClassScope.DefaultProperty;
  5307. if PropEl<>nil then
  5308. begin
  5309. // class has default property
  5310. if (ResolvedValue.IdentEl is TPasType) and (not PropEl.IsClass) then
  5311. RaiseMsg(20170216152213,nIllegalQualifier,sIllegalQualifier,['['],Params);
  5312. Value:=Params.Value;
  5313. if Value.CustomData is TResolvedReference then
  5314. SetResolvedRefAccess(Value,TResolvedReference(Value.CustomData),rraRead);
  5315. CreateReference(PropEl,Params,Access);
  5316. CheckCallPropertyCompatibility(PropEl,Params,true);
  5317. FinishPropertyParamAccess(Params,PropEl);
  5318. exit(true);
  5319. end;
  5320. Result:=false;
  5321. end;
  5322. procedure TPasResolver.ResolveSetParamsExpr(Params: TParamsExpr);
  5323. // e.g. resolving '[1,2..3]'
  5324. begin
  5325. {$IFDEF VerbosePasResolver}
  5326. writeln('TPasResolver.ResolveSetParamsExpr ',GetTreeDbg(Params));
  5327. {$ENDIF}
  5328. if Params.Value<>nil then
  5329. RaiseNotYetImplemented(20160930135910,Params);
  5330. end;
  5331. procedure TPasResolver.ResolveArrayValues(El: TArrayValues);
  5332. var
  5333. i: Integer;
  5334. begin
  5335. for i:=0 to length(El.Values)-1 do
  5336. ResolveExpr(El.Values[i],rraRead);
  5337. end;
  5338. procedure TPasResolver.SetResolvedRefAccess(Expr: TPasExpr;
  5339. Ref: TResolvedReference; Access: TResolvedRefAccess);
  5340. begin
  5341. if (Ref.Access=Access) then exit;
  5342. if Access in [rraNone,rraParamToUnknownProc] then
  5343. exit;
  5344. if Expr=nil then ;
  5345. case Ref.Access of
  5346. rraNone,rraParamToUnknownProc:
  5347. Ref.Access:=Access;
  5348. rraRead:
  5349. if Access in [rraAssign,rraReadAndAssign,rraVarParam,rraOutParam] then
  5350. Ref.Access:=rraReadAndAssign
  5351. else
  5352. exit;
  5353. rraAssign,rraOutParam:
  5354. if Access in [rraRead,rraReadAndAssign,rraVarParam] then
  5355. Ref.Access:=rraReadAndAssign
  5356. else
  5357. exit;
  5358. rraReadAndAssign: exit;
  5359. rraVarParam: exit;
  5360. else
  5361. RaiseInternalError(20170403163727);
  5362. end;
  5363. end;
  5364. procedure TPasResolver.AccessExpr(Expr: TPasExpr;
  5365. Access: TResolvedRefAccess);
  5366. // called after a call target was found, called for each element
  5367. // to set the rraParamToUnknownProc to Access
  5368. var
  5369. Ref: TResolvedReference;
  5370. Bin: TBinaryExpr;
  5371. Params: TParamsExpr;
  5372. ValueResolved: TPasResolverResult;
  5373. C: TClass;
  5374. begin
  5375. if (Expr.CustomData is TResolvedReference) then
  5376. begin
  5377. Ref:=TResolvedReference(Expr.CustomData);
  5378. SetResolvedRefAccess(Expr,Ref,Access);
  5379. end;
  5380. C:=Expr.ClassType;
  5381. if C=TBinaryExpr then
  5382. begin
  5383. Bin:=TBinaryExpr(Expr);
  5384. if Bin.OpCode in [eopSubIdent,eopNone] then
  5385. AccessExpr(Bin.right,Access);
  5386. end
  5387. else if C=TParamsExpr then
  5388. begin
  5389. Params:=TParamsExpr(Expr);
  5390. case Params.Kind of
  5391. pekFuncParams:
  5392. if IsTypeCast(Params) then
  5393. AccessExpr(Params.Params[0],Access)
  5394. else
  5395. AccessExpr(Params.Value,Access);
  5396. pekArrayParams:
  5397. begin
  5398. ComputeElement(Params.Value,ValueResolved,[]);
  5399. if not IsDynArray(ValueResolved.TypeEl) then
  5400. AccessExpr(Params.Value,Access);
  5401. end;
  5402. pekSet:
  5403. if Access<>rraRead then
  5404. RaiseMsg(20170306112306,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Expr);
  5405. else
  5406. RaiseNotYetImplemented(20170403173831,Params);
  5407. end;
  5408. end
  5409. else if (C=TSelfExpr) or ((C=TPrimitiveExpr) and (TPrimitiveExpr(Expr).Kind=pekIdent)) then
  5410. // ok
  5411. else if (Access in [rraRead,rraParamToUnknownProc])
  5412. and ((C=TPrimitiveExpr)
  5413. or (C=TNilExpr)
  5414. or (C=TBoolConstExpr)) then
  5415. // ok
  5416. else if C=TUnaryExpr then
  5417. AccessExpr(TUnaryExpr(Expr).Operand,Access)
  5418. else
  5419. begin
  5420. {$IFDEF VerbosePasResolver}
  5421. writeln('TPasResolver.AccessExpr Expr=',GetObjName(Expr),' Access=',Access,' Declaration="',Expr.GetDeclaration(false),'"');
  5422. {$ENDIF}
  5423. RaiseNotYetImplemented(20170306102158,Expr);
  5424. end;
  5425. end;
  5426. procedure TPasResolver.CheckPendingForwards(El: TPasElement);
  5427. var
  5428. i: Integer;
  5429. DeclEl: TPasElement;
  5430. Proc: TPasProcedure;
  5431. aClassType: TPasClassType;
  5432. begin
  5433. if El is TPasDeclarations then
  5434. begin
  5435. for i:=0 to TPasDeclarations(El).Declarations.Count-1 do
  5436. begin
  5437. DeclEl:=TPasElement(TPasDeclarations(El).Declarations[i]);
  5438. if DeclEl is TPasProcedure then
  5439. begin
  5440. Proc:=TPasProcedure(DeclEl);
  5441. if ProcNeedsImplProc(Proc)
  5442. and (TPasProcedureScope(Proc.CustomData).ImplProc=nil) then
  5443. RaiseMsg(20170216152219,nForwardProcNotResolved,sForwardProcNotResolved,
  5444. [Proc.ElementTypeName,Proc.Name],Proc);
  5445. end;
  5446. end;
  5447. end
  5448. else if El.ClassType=TPasClassType then
  5449. begin
  5450. aClassType:=TPasClassType(El);
  5451. for i:=0 to aClassType.Members.Count-1 do
  5452. begin
  5453. DeclEl:=TPasElement(aClassType.Members[i]);
  5454. if DeclEl is TPasProcedure then
  5455. begin
  5456. Proc:=TPasProcedure(DeclEl);
  5457. if Proc.IsAbstract or Proc.IsExternal then continue;
  5458. if TPasProcedureScope(Proc.CustomData).ImplProc=nil then
  5459. RaiseMsg(20170216152221,nForwardProcNotResolved,sForwardProcNotResolved,
  5460. [Proc.ElementTypeName,Proc.Name],Proc);
  5461. end;
  5462. end;
  5463. end;
  5464. end;
  5465. procedure TPasResolver.AddModule(El: TPasModule);
  5466. var
  5467. C: TClass;
  5468. ModScope: TPasModuleScope;
  5469. begin
  5470. if TopScope<>DefaultScope then
  5471. RaiseInvalidScopeForElement(20160922163504,El);
  5472. ModScope:=TPasModuleScope(PushScope(El,TPasModuleScope));
  5473. ModScope.VisibilityContext:=El;
  5474. ModScope.FirstName:=FirstDottedIdentifier(El.Name);
  5475. C:=El.ClassType;
  5476. if (C=TPasProgram) or (C=TPasLibrary) or (C=TPasPackage) then
  5477. FDefaultNameSpace:=ChompDottedIdentifier(El.Name)
  5478. else
  5479. FDefaultNameSpace:='';
  5480. end;
  5481. procedure TPasResolver.AddSection(El: TPasSection);
  5482. // TInterfaceSection, TImplementationSection, TProgramSection, TLibrarySection
  5483. // Note: implementation scope is within the interface scope
  5484. begin
  5485. FPendingForwards.Add(El); // check forward declarations at the end
  5486. PushScope(El,TPasSectionScope);
  5487. end;
  5488. procedure TPasResolver.AddType(El: TPasType);
  5489. begin
  5490. if (El.Name='') then exit; // sub type
  5491. {$IFDEF VerbosePasResolver}
  5492. writeln('TPasResolver.AddType El=',GetObjName(El),' El.Parent=',GetObjName(El.Parent));
  5493. {$ENDIF}
  5494. if not (TopScope is TPasIdentifierScope) then
  5495. RaiseInvalidScopeForElement(20160922163506,El);
  5496. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5497. end;
  5498. procedure TPasResolver.AddRecordType(El: TPasRecordType);
  5499. begin
  5500. {$IFDEF VerbosePasResolver}
  5501. writeln('TPasResolver.AddRecordType ',GetObjName(El),' Parent=',GetObjName(El.Parent));
  5502. {$ENDIF}
  5503. if not (TopScope is TPasIdentifierScope) then
  5504. RaiseInvalidScopeForElement(20160922163508,El);
  5505. if El.Name<>'' then begin
  5506. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5507. FPendingForwards.Add(El); // check forward declarations at the end
  5508. end;
  5509. if El.Parent.ClassType<>TPasVariant then
  5510. PushScope(El,TPasRecordScope);
  5511. end;
  5512. procedure TPasResolver.AddClassType(El: TPasClassType);
  5513. var
  5514. Duplicate: TPasIdentifier;
  5515. ForwardDecl: TPasClassType;
  5516. begin
  5517. {$IFDEF VerbosePasResolver}
  5518. writeln('TPasResolver.AddClassType ',GetObjName(El),' Parent=',GetObjName(El.Parent),' ',GetElementSourcePosStr(El));
  5519. {$ENDIF}
  5520. if not (TopScope is TPasIdentifierScope) then
  5521. RaiseInvalidScopeForElement(20160922163510,El);
  5522. Duplicate:=TPasIdentifierScope(TopScope).FindIdentifier(El.Name);
  5523. //if Duplicate<>nil then
  5524. //writeln(' Duplicate=',GetObjName(Duplicate.Element),' ',ord(Duplicate.Kind));
  5525. if (Duplicate<>nil)
  5526. and (Duplicate.Kind=pikSimple)
  5527. and (Duplicate.Element<>nil)
  5528. and (Duplicate.Element.Parent=El.Parent)
  5529. and (Duplicate.Element is TPasClassType)
  5530. and TPasClassType(Duplicate.Element).IsForward
  5531. then
  5532. begin
  5533. // forward declaration found
  5534. ForwardDecl:=TPasClassType(Duplicate.Element);
  5535. {$IFDEF VerbosePasResolver}
  5536. writeln(' Resolving Forward=',GetObjName(ForwardDecl),' ',GetElementSourcePosStr(ForwardDecl));
  5537. {$ENDIF}
  5538. if ForwardDecl.CustomData<>nil then
  5539. RaiseInternalError(20160922163513,'forward class has already customdata');
  5540. // create a ref from the forward to the real declaration
  5541. CreateReference(El,ForwardDecl,rraRead);
  5542. // change the cache item
  5543. Duplicate.Element:=El;
  5544. end
  5545. else
  5546. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5547. FPendingForwards.Add(El); // check forward declarations at the end
  5548. end;
  5549. procedure TPasResolver.AddVariable(El: TPasVariable);
  5550. begin
  5551. if (El.Name='') then exit; // anonymous var
  5552. {$IFDEF VerbosePasResolver}
  5553. writeln('TPasResolver.AddVariable ',GetObjName(El));
  5554. {$ENDIF}
  5555. if not (TopScope is TPasIdentifierScope) then
  5556. RaiseInvalidScopeForElement(20160929205730,El);
  5557. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5558. end;
  5559. procedure TPasResolver.AddEnumType(El: TPasEnumType);
  5560. var
  5561. CanonicalSet: TPasSetType;
  5562. begin
  5563. {$IFDEF VerbosePasResolver}
  5564. writeln('TPasResolver.AddEnumType ',GetObjName(El));
  5565. {$ENDIF}
  5566. if not (TopScope is TPasIdentifierScope) then
  5567. RaiseInvalidScopeForElement(20160929205732,El);
  5568. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5569. PushScope(El,TPasEnumTypeScope);
  5570. // add canonical set
  5571. CanonicalSet:=TPasSetType.Create('',El);
  5572. CanonicalSet.EnumType:=El;
  5573. El.AddRef;
  5574. TPasEnumTypeScope(TopScope).CanonicalSet:=CanonicalSet;
  5575. end;
  5576. procedure TPasResolver.AddEnumValue(El: TPasEnumValue);
  5577. var
  5578. i: Integer;
  5579. Scope: TPasScope;
  5580. Old: TPasIdentifier;
  5581. begin
  5582. {$IFDEF VerbosePasResolver}
  5583. writeln('TPasResolver.AddEnumValue ',GetObjName(El));
  5584. {$ENDIF}
  5585. if not (TopScope is TPasEnumTypeScope) then
  5586. RaiseInvalidScopeForElement(20160929205736,El);
  5587. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5588. // propagate enum to parent scopes
  5589. for i:=ScopeCount-2 downto 0 do
  5590. begin
  5591. Scope:=Scopes[i];
  5592. if (Scope is TPasClassScope) or (Scope is TPasRecordScope) then
  5593. begin
  5594. // class or record: add if not duplicate
  5595. Old:=TPasIdentifierScope(Scope).FindIdentifier(El.Name);
  5596. if Old=nil then
  5597. TPasIdentifierScope(Scope).AddIdentifier(El.Name,El,pikSimple);
  5598. end
  5599. else if (Scope is TPasProcedureScope) or (Scope is TPasSectionScope) then
  5600. begin
  5601. // procedure or section: check for duplicate and add
  5602. Old:=TPasIdentifierScope(Scope).FindLocalIdentifier(El.Name);
  5603. if Old<>nil then
  5604. RaiseMsg(20170216152224,nDuplicateIdentifier,sDuplicateIdentifier,
  5605. [El.Name,GetElementSourcePosStr(Old.Element)],El);
  5606. TPasIdentifierScope(Scope).AddIdentifier(El.Name,El,pikSimple);
  5607. break;
  5608. end
  5609. else
  5610. break;
  5611. end;
  5612. end;
  5613. procedure TPasResolver.AddProperty(El: TPasProperty);
  5614. begin
  5615. if (El.Name='') then
  5616. RaiseNotYetImplemented(20160922163518,El);
  5617. {$IFDEF VerbosePasResolver}
  5618. writeln('TPasResolver.AddProperty ',GetObjName(El));
  5619. {$ENDIF}
  5620. if not (TopScope is TPasClassScope) then
  5621. RaiseInvalidScopeForElement(20160922163520,El);
  5622. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5623. PushScope(El,TPasPropertyScope);
  5624. end;
  5625. procedure TPasResolver.AddProcedure(El: TPasProcedure);
  5626. var
  5627. ProcName, aClassName: String;
  5628. p: SizeInt;
  5629. CurClassType: TPasClassType;
  5630. ProcScope: TPasProcedureScope;
  5631. NeedPop, HasDot: Boolean;
  5632. begin
  5633. {$IFDEF VerbosePasResolver}
  5634. writeln('TPasResolver.AddProcedure ',GetObjName(El));
  5635. {$ENDIF}
  5636. if not (TopScope is TPasIdentifierScope) then
  5637. RaiseInvalidScopeForElement(20160922163522,El);
  5638. // Note: El.ProcType is nil !
  5639. ProcName:=El.Name;
  5640. HasDot:=Pos('.',ProcName)>1;
  5641. if not HasDot then
  5642. AddIdentifier(TPasIdentifierScope(TopScope),ProcName,El,pikProc);
  5643. ProcScope:=TPasProcedureScope(PushScope(El,TPasProcedureScope));
  5644. if HasDot then
  5645. begin
  5646. // method implementation -> search class
  5647. {$IFDEF VerbosePasResolver}
  5648. writeln('TPasResolver.AddProcedure searching class of "',ProcName,'" ...');
  5649. {$ENDIF}
  5650. CurClassType:=nil;
  5651. repeat
  5652. p:=Pos('.',ProcName);
  5653. if p<1 then
  5654. begin
  5655. if CurClassType=nil then
  5656. RaiseInternalError(20161013170829);
  5657. break;
  5658. end;
  5659. aClassName:=LeftStr(ProcName,p-1);
  5660. Delete(ProcName,1,p);
  5661. {$IFDEF VerbosePasResolver}
  5662. writeln('TPasResolver.AddProcedure searching class "',aClassName,'" ProcName="',ProcName,'" ...');
  5663. {$ENDIF}
  5664. if not IsValidIdent(aClassName) then
  5665. RaiseNotYetImplemented(20161013170844,El);
  5666. if CurClassType<>nil then
  5667. begin
  5668. NeedPop:=true;
  5669. PushClassDotScope(CurClassType);
  5670. end
  5671. else
  5672. NeedPop:=false;
  5673. CurClassType:=TPasClassType(FindElementWithoutParams(aClassName,El,false));
  5674. if not (CurClassType is TPasClassType) then
  5675. begin
  5676. aClassName:=LeftStr(El.Name,length(El.Name)-length(ProcName));
  5677. RaiseXExpectedButYFound(20170216152557,'class',aClassname+':'+CurClassType.ElementTypeName,El);
  5678. end;
  5679. // restore scope
  5680. if NeedPop then
  5681. PopScope;
  5682. until false;
  5683. if not IsValidIdent(ProcName) then
  5684. RaiseNotYetImplemented(20161013170956,El);
  5685. ProcScope.VisibilityContext:=CurClassType;
  5686. ProcScope.ClassScope:=CurClassType.CustomData as TPasClassScope;
  5687. end;
  5688. end;
  5689. procedure TPasResolver.AddArgument(El: TPasArgument);
  5690. var
  5691. ProcType: TPasProcedureType;
  5692. i: Integer;
  5693. Arg: TPasArgument;
  5694. begin
  5695. if (El.Name='') then
  5696. RaiseInternalError(20160922163526,GetObjName(El));
  5697. {$IFDEF VerbosePasResolver}
  5698. writeln('TPasResolver.AddArgument ',GetObjName(El));
  5699. {$ENDIF}
  5700. if (TopScope=nil) then
  5701. RaiseInvalidScopeForElement(20160922163529,El);
  5702. if El.Parent.ClassType=TPasProperty then
  5703. begin
  5704. if TopScope.ClassType<>TPasPropertyScope then
  5705. RaiseInvalidScopeForElement(20161014124530,El);
  5706. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5707. end
  5708. else if El.Parent is TPasProcedureType then
  5709. begin
  5710. ProcType:=TPasProcedureType(El.Parent);
  5711. if ProcType.Parent is TPasProcedure then
  5712. begin
  5713. if TopScope.ClassType<>TPasProcedureScope then
  5714. RaiseInvalidScopeForElement(20160922163529,El);
  5715. AddIdentifier(TPasIdentifierScope(TopScope),El.Name,El,pikSimple);
  5716. end
  5717. else
  5718. begin
  5719. for i:=0 to ProcType.Args.Count-1 do
  5720. begin
  5721. Arg:=TPasArgument(ProcType.Args[i]);
  5722. if (Arg<>El) and (CompareText(TPasArgument(ProcType.Args[i]).Name,El.Name)=0) then
  5723. RaiseMsg(20170216152225,nDuplicateIdentifier,sDuplicateIdentifier,[Arg.Name,GetElementSourcePosStr(Arg)],El);
  5724. end;
  5725. end;
  5726. end
  5727. else
  5728. RaiseNotYetImplemented(20161014124937,El);
  5729. end;
  5730. procedure TPasResolver.AddFunctionResult(El: TPasResultElement);
  5731. begin
  5732. if TopScope.ClassType<>TPasProcedureScope then exit;
  5733. if not (El.Parent is TPasProcedure) then exit;
  5734. AddIdentifier(TPasProcedureScope(TopScope),ResolverResultVar,El,pikSimple);
  5735. end;
  5736. procedure TPasResolver.AddExceptOn(El: TPasImplExceptOn);
  5737. begin
  5738. PushScope(El,TPasExceptOnScope);
  5739. end;
  5740. procedure TPasResolver.AddProcedureBody(El: TProcedureBody);
  5741. begin
  5742. if El=nil then ;
  5743. CheckTopScope(TPasProcedureScope);
  5744. end;
  5745. procedure TPasResolver.WriteScopes;
  5746. var
  5747. i: Integer;
  5748. Scope: TPasScope;
  5749. begin
  5750. writeln('TPasResolver.WriteScopes ScopeCount=',ScopeCount);
  5751. for i:=ScopeCount-1 downto 0 do
  5752. begin
  5753. Scope:=Scopes[i];
  5754. writeln(' ',i,'/',ScopeCount,' ',GetObjName(Scope));
  5755. Scope.WriteIdentifiers(' ');
  5756. end;
  5757. end;
  5758. procedure TPasResolver.ComputeBinaryExpr(Bin: TBinaryExpr; out
  5759. ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  5760. StartEl: TPasElement);
  5761. procedure SetBaseType(BaseType: TResolverBaseType);
  5762. begin
  5763. SetResolverValueExpr(ResolvedEl,BaseType,FBaseTypes[BaseType],Bin,[rrfReadable]);
  5764. end;
  5765. var
  5766. LeftResolved, RightResolved: TPasResolverResult;
  5767. LeftTypeEl, RightTypeEl: TPasType;
  5768. begin
  5769. if (Bin.OpCode=eopSubIdent)
  5770. or ((Bin.OpCode=eopNone) and (Bin.left is TInheritedExpr)) then
  5771. begin
  5772. // Note: bin.left was already resolved via ResolveSubIdent
  5773. ComputeElement(Bin.right,ResolvedEl,Flags,StartEl);
  5774. exit;
  5775. end;
  5776. if Bin.OpCode in [eopEqual,eopNotEqual] then
  5777. begin
  5778. if CheckEqualElCompatibility(Bin.left,Bin.right,nil,true,
  5779. rcSetReferenceFlags in Flags)=cIncompatible then
  5780. RaiseInternalError(20161007215912);
  5781. SetBaseType(btBoolean);
  5782. exit;
  5783. end;
  5784. ComputeElement(Bin.left,LeftResolved,Flags-[rcNoImplicitProc],StartEl);
  5785. ComputeElement(Bin.right,RightResolved,Flags-[rcNoImplicitProc],StartEl);
  5786. // ToDo: check operator overloading
  5787. //writeln('TPasResolver.ComputeBinaryExpr ',OpcodeStrings[Bin.OpCode],' Left=',GetResolverResultDbg(LeftResolved),' Right=',GetResolverResultDbg(RightResolved));
  5788. if LeftResolved.BaseType in btAllInteger then
  5789. begin
  5790. if (rrfReadable in LeftResolved.Flags)
  5791. and (rrfReadable in RightResolved.Flags) then
  5792. begin
  5793. if (RightResolved.BaseType in (btAllInteger+btAllFloats)) then
  5794. case Bin.OpCode of
  5795. eopNone:
  5796. if (Bin.Kind=pekRange) then
  5797. begin
  5798. if not (RightResolved.BaseType in btAllInteger) then
  5799. RaiseXExpectedButYFound(20170216152600,'integer',BaseTypeNames[RightResolved.BaseType],Bin.right);
  5800. SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,LeftResolved.TypeEl,Bin,[rrfReadable]);
  5801. if Bin.Parent is TPasRangeType then
  5802. ResolvedEl.TypeEl:=TPasRangeType(Bin.Parent);
  5803. exit;
  5804. end;
  5805. eopAdd, eopSubtract,
  5806. eopMultiply, eopDiv, eopMod,
  5807. eopPower,
  5808. eopShl, eopShr,
  5809. eopAnd, eopOr, eopXor:
  5810. begin
  5811. // use left type for result
  5812. SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,LeftResolved.TypeEl,Bin,[rrfReadable]);
  5813. exit;
  5814. end;
  5815. eopLessThan,
  5816. eopGreaterThan,
  5817. eopLessthanEqual,
  5818. eopGreaterThanEqual:
  5819. begin
  5820. SetBaseType(btBoolean);
  5821. exit;
  5822. end;
  5823. eopDivide:
  5824. begin
  5825. SetBaseType(BaseTypeExtended);
  5826. exit;
  5827. end;
  5828. end
  5829. else if (RightResolved.BaseType=btSet) and (RightResolved.SubType in btAllInteger)
  5830. and (Bin.OpCode=eopIn) then
  5831. begin
  5832. SetBaseType(btBoolean);
  5833. exit;
  5834. end;
  5835. end;
  5836. end
  5837. else if LeftResolved.BaseType in btAllBooleans then
  5838. begin
  5839. if (rrfReadable in LeftResolved.Flags)
  5840. and (RightResolved.BaseType in btAllBooleans)
  5841. and (rrfReadable in RightResolved.Flags) then
  5842. case Bin.OpCode of
  5843. eopNone:
  5844. if Bin.Kind=pekRange then
  5845. begin
  5846. SetResolverValueExpr(ResolvedEl,btRange,FBaseTypes[LeftResolved.BaseType],Bin,[rrfReadable]);
  5847. ResolvedEl.SubType:=LeftResolved.BaseType;
  5848. exit;
  5849. end;
  5850. eopAnd, eopOr, eopXor:
  5851. begin
  5852. // use left type for result
  5853. SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,LeftResolved.TypeEl,Bin,[rrfReadable]);
  5854. exit;
  5855. end;
  5856. end;
  5857. end
  5858. else if LeftResolved.BaseType in btAllStringAndChars then
  5859. begin
  5860. if (rrfReadable in LeftResolved.Flags)
  5861. and (rrfReadable in RightResolved.Flags) then
  5862. begin
  5863. if (RightResolved.BaseType in btAllStringAndChars) then
  5864. case Bin.OpCode of
  5865. eopNone:
  5866. if (Bin.Kind=pekRange) and (LeftResolved.BaseType in btAllChars) then
  5867. begin
  5868. if not (RightResolved.BaseType in btAllChars) then
  5869. RaiseXExpectedButYFound(20170216152603,'char',BaseTypeNames[RightResolved.BaseType],Bin.right);
  5870. SetResolverValueExpr(ResolvedEl,btRange,FBaseTypes[LeftResolved.BaseType],Bin,[rrfReadable]);
  5871. ResolvedEl.SubType:=LeftResolved.BaseType;
  5872. exit;
  5873. end;
  5874. eopAdd:
  5875. case LeftResolved.BaseType of
  5876. btChar:
  5877. begin
  5878. case RightResolved.BaseType of
  5879. btChar: SetBaseType(btString);
  5880. btAnsiChar:
  5881. if BaseTypeChar=btAnsiChar then
  5882. SetBaseType(btString)
  5883. else
  5884. SetBaseType(btUnicodeString);
  5885. btWideChar:
  5886. if BaseTypeChar=btWideChar then
  5887. SetBaseType(btString)
  5888. else
  5889. SetBaseType(btUnicodeString);
  5890. else
  5891. // use right type for result
  5892. SetResolverValueExpr(ResolvedEl,RightResolved.BaseType,RightResolved.TypeEl,Bin,[rrfReadable]);
  5893. end;
  5894. exit;
  5895. end;
  5896. btAnsiChar:
  5897. begin
  5898. case RightResolved.BaseType of
  5899. btChar:
  5900. if BaseTypeChar=btAnsiChar then
  5901. SetBaseType(btString)
  5902. else
  5903. SetBaseType(btUnicodeString);
  5904. btAnsiChar:
  5905. if BaseTypeChar=btAnsiChar then
  5906. SetBaseType(btString)
  5907. else
  5908. SetBaseType(btAnsiString);
  5909. btWideChar:
  5910. if BaseTypeChar=btWideChar then
  5911. SetBaseType(btString)
  5912. else
  5913. SetBaseType(btUnicodeString);
  5914. else
  5915. // use right type for result
  5916. SetResolverValueExpr(ResolvedEl,RightResolved.BaseType,RightResolved.TypeEl,Bin,[rrfReadable]);
  5917. end;
  5918. exit;
  5919. end;
  5920. btWideChar:
  5921. begin
  5922. case RightResolved.BaseType of
  5923. btChar,btAnsiChar,btWideChar:
  5924. if BaseTypeChar=btWideChar then
  5925. SetBaseType(btString)
  5926. else
  5927. SetBaseType(btUnicodeString);
  5928. else
  5929. // use right type for result
  5930. SetResolverValueExpr(ResolvedEl,RightResolved.BaseType,RightResolved.TypeEl,Bin,[rrfReadable]);
  5931. end;
  5932. exit;
  5933. end;
  5934. btShortString:
  5935. begin
  5936. case RightResolved.BaseType of
  5937. btChar,btAnsiChar,btShortString,btWideChar:
  5938. // use left type for result
  5939. SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,LeftResolved.TypeEl,Bin,[rrfReadable]);
  5940. else
  5941. // shortstring + string => string
  5942. SetResolverValueExpr(ResolvedEl,RightResolved.BaseType,RightResolved.TypeEl,Bin,[rrfReadable]);
  5943. end;
  5944. exit;
  5945. end;
  5946. btString,btAnsiString,btUnicodeString:
  5947. begin
  5948. // string + x => string
  5949. SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,LeftResolved.TypeEl,Bin,[rrfReadable]);
  5950. exit;
  5951. end;
  5952. end;
  5953. eopLessThan,
  5954. eopGreaterThan,
  5955. eopLessthanEqual,
  5956. eopGreaterThanEqual:
  5957. begin
  5958. SetBaseType(btBoolean);
  5959. exit;
  5960. end;
  5961. end
  5962. else if (RightResolved.BaseType=btSet)
  5963. and (RightResolved.SubType in btAllChars)
  5964. and (LeftResolved.BaseType in btAllChars) then
  5965. begin
  5966. case Bin.OpCode of
  5967. eopIn:
  5968. begin
  5969. SetBaseType(btBoolean);
  5970. exit;
  5971. end;
  5972. end;
  5973. end
  5974. end
  5975. end
  5976. else if LeftResolved.BaseType in btAllFloats then
  5977. begin
  5978. if (rrfReadable in LeftResolved.Flags)
  5979. and (RightResolved.BaseType in (btAllInteger+btAllFloats))
  5980. and (rrfReadable in RightResolved.Flags) then
  5981. case Bin.OpCode of
  5982. eopAdd, eopSubtract,
  5983. eopMultiply, eopDivide, eopMod,
  5984. eopPower:
  5985. begin
  5986. SetResolverValueExpr(ResolvedEl,LeftResolved.BaseType,LeftResolved.TypeEl,Bin,[rrfReadable]);
  5987. exit;
  5988. end;
  5989. eopLessThan,
  5990. eopGreaterThan,
  5991. eopLessthanEqual,
  5992. eopGreaterThanEqual:
  5993. begin
  5994. SetBaseType(btBoolean);
  5995. exit;
  5996. end;
  5997. end;
  5998. end
  5999. else if LeftResolved.BaseType=btPointer then
  6000. begin
  6001. if (rrfReadable in LeftResolved.Flags)
  6002. and (RightResolved.BaseType in btAllInteger)
  6003. and (rrfReadable in RightResolved.Flags) then
  6004. case Bin.OpCode of
  6005. eopAdd,eopSubtract:
  6006. begin
  6007. SetResolverValueExpr(ResolvedEl,btPointer,LeftResolved.TypeEl,Bin,[rrfReadable]);
  6008. exit;
  6009. end;
  6010. end
  6011. else if RightResolved.BaseType=btPointer then
  6012. case Bin.OpCode of
  6013. eopLessThan,
  6014. eopGreaterThan,
  6015. eopLessthanEqual,
  6016. eopGreaterThanEqual:
  6017. begin
  6018. SetBaseType(btBoolean);
  6019. exit;
  6020. end;
  6021. end;
  6022. end
  6023. else if LeftResolved.BaseType=btContext then
  6024. case Bin.OpCode of
  6025. eopNone:
  6026. if Bin.Kind=pekRange then
  6027. begin
  6028. if (rrfReadable in LeftResolved.Flags)
  6029. and (rrfReadable in RightResolved.Flags) then
  6030. begin
  6031. CheckSetLitElCompatible(Bin.left,Bin.right,LeftResolved,RightResolved);
  6032. ResolvedEl:=LeftResolved;
  6033. ResolvedEl.SubType:=ResolvedEl.BaseType;
  6034. ResolvedEl.BaseType:=btRange;
  6035. ResolvedEl.ExprEl:=Bin;
  6036. exit;
  6037. end;
  6038. end;
  6039. eopIn:
  6040. if (rrfReadable in LeftResolved.Flags)
  6041. and (rrfReadable in RightResolved.Flags) then
  6042. begin
  6043. if LeftResolved.BaseType in (btAllInteger+btAllChars) then
  6044. begin
  6045. if (RightResolved.BaseType<>btSet) then
  6046. RaiseXExpectedButYFound(20170216152607,'set of '+BaseTypeNames[LeftResolved.BaseType],LeftResolved.TypeEl.ElementTypeName,Bin.right);
  6047. if LeftResolved.BaseType in btAllChars then
  6048. begin
  6049. if not (RightResolved.SubType in btAllChars) then
  6050. RaiseXExpectedButYFound(20170216152609,'set of '+BaseTypeNames[LeftResolved.BaseType],'set of '+BaseTypeNames[RightResolved.SubType],Bin.right);
  6051. end
  6052. else if not (RightResolved.SubType in btAllInteger) then
  6053. RaiseXExpectedButYFound(20170216152612,'set of '+BaseTypeNames[LeftResolved.BaseType],'set of '+BaseTypeNames[RightResolved.SubType],Bin.right);
  6054. SetBaseType(btBoolean);
  6055. exit;
  6056. end
  6057. else if (LeftResolved.BaseType=btContext) and (LeftResolved.TypeEl is TPasEnumType) then
  6058. begin
  6059. if (RightResolved.BaseType<>btSet) then
  6060. RaiseXExpectedButYFound(20170216152615,'set of '+LeftResolved.TypeEl.Name,LeftResolved.TypeEl.ElementTypeName,Bin.right);
  6061. if LeftResolved.TypeEl<>RightResolved.TypeEl then
  6062. RaiseXExpectedButYFound(20170216152618,'set of '+LeftResolved.TypeEl.Name,'set of '+RightResolved.TypeEl.Name,Bin.right);
  6063. SetBaseType(btBoolean);
  6064. exit;
  6065. end
  6066. else
  6067. RaiseMsg(20170216152228,nInOperatorExpectsSetElementButGot,
  6068. sInOperatorExpectsSetElementButGot,[LeftResolved.TypeEl.ElementTypeName],Bin);
  6069. end;
  6070. eopIs:
  6071. begin
  6072. if (LeftResolved.TypeEl is TPasClassType) then
  6073. begin
  6074. if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType) then
  6075. RaiseMsg(20170216152230,nIllegalQualifier,sIllegalQualifier,['is'],Bin);
  6076. // left side is a class instance
  6077. if RightResolved.IdentEl is TPasClassType then
  6078. begin
  6079. // e.g. if Image is TFPMemoryImage then ;
  6080. // Note: at compile time the check is reversed: right must inherit from left
  6081. if CheckSrcIsADstType(RightResolved,LeftResolved,Bin)<>cIncompatible then
  6082. begin
  6083. SetBaseType(btBoolean);
  6084. exit;
  6085. end
  6086. else if CheckSrcIsADstType(LeftResolved,RightResolved,Bin)<>cIncompatible then
  6087. begin
  6088. // e.g. if Image is TObject then ;
  6089. // This is useful after some unchecked typecast -> allow
  6090. SetBaseType(btBoolean);
  6091. exit;
  6092. end;
  6093. {$IFDEF VerbosePasResolver}
  6094. writeln('TPasResolver.ComputeBinaryExpr LeftClass=',GetClassAncestorsDbg(TPasClassType(LeftResolved.TypeEl)));
  6095. writeln('TPasResolver.ComputeBinaryExpr RightClass=',GetClassAncestorsDbg(TPasClassType(RightResolved.IdentEl)));
  6096. {$ENDIF}
  6097. end
  6098. else if (RightResolved.TypeEl is TPasClassOfType)
  6099. and (rrfReadable in RightResolved.Flags) then
  6100. begin
  6101. // e.g. if Image is ImageClass then ;
  6102. if (CheckClassesAreRelated(LeftResolved.TypeEl,
  6103. TPasClassOfType(RightResolved.TypeEl).DestType,Bin)<>cIncompatible) then
  6104. begin
  6105. SetBaseType(btBoolean);
  6106. exit;
  6107. end;
  6108. end
  6109. else
  6110. RaiseXExpectedButYFound(20170216152625,'class type',RightResolved.TypeEl.ElementTypeName,Bin.right);
  6111. end
  6112. else if (proClassOfIs in Options) and (LeftResolved.TypeEl is TPasClassOfType)
  6113. and (rrfReadable in LeftResolved.Flags) then
  6114. begin
  6115. if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType) then
  6116. RaiseMsg(20170322101128,nIllegalQualifier,sIllegalQualifier,['is'],Bin);
  6117. // left side is class-of variable
  6118. LeftTypeEl:=TPasClassOfType(LeftResolved.TypeEl).DestType;
  6119. if RightResolved.IdentEl is TPasClassType then
  6120. begin
  6121. // e.g. if ImageClass is TFPMemoryImage then ;
  6122. // Note: at compile time the check is reversed: right must inherit from left
  6123. if CheckClassIsClass(RightResolved.TypeEl,LeftTypeEl,Bin)<>cIncompatible then
  6124. begin
  6125. SetBaseType(btBoolean);
  6126. exit;
  6127. end
  6128. end
  6129. else if (RightResolved.TypeEl is TPasClassOfType) then
  6130. begin
  6131. // e.g. if ImageClassA is ImageClassB then ;
  6132. // or if ImageClassA is TFPImageClass then ;
  6133. RightTypeEl:=TPasClassOfType(RightResolved.TypeEl).DestType;
  6134. if (CheckClassesAreRelated(LeftTypeEl,RightTypeEl,Bin)<>cIncompatible) then
  6135. begin
  6136. SetBaseType(btBoolean);
  6137. exit;
  6138. end
  6139. end
  6140. else
  6141. RaiseXExpectedButYFound(20170322105252,'class type',RightResolved.TypeEl.ElementTypeName,Bin.right);
  6142. end
  6143. else if LeftResolved.TypeEl=nil then
  6144. RaiseMsg(20170216152232,nLeftSideOfIsOperatorExpectsAClassButGot,sLeftSideOfIsOperatorExpectsAClassButGot,
  6145. [BaseTypeNames[LeftResolved.BaseType]],Bin.left)
  6146. else
  6147. RaiseMsg(20170216152234,nLeftSideOfIsOperatorExpectsAClassButGot,sLeftSideOfIsOperatorExpectsAClassButGot,
  6148. [LeftResolved.TypeEl.ElementTypeName],Bin.left);
  6149. {$IFDEF VerbosePasResolver}
  6150. writeln('TPasResolver.ComputeBinaryExpr is-operator: left=',GetResolverResultDbg(LeftResolved),' right=',GetResolverResultDbg(RightResolved));
  6151. {$ENDIF}
  6152. RaiseMsg(20170216152236,nTypesAreNotRelated,sTypesAreNotRelated,[],Bin);
  6153. end;
  6154. eopAs:
  6155. begin
  6156. if (LeftResolved.TypeEl is TPasClassType) then
  6157. begin
  6158. if (LeftResolved.IdentEl=nil) or (LeftResolved.IdentEl is TPasType)
  6159. or (not (rrfReadable in LeftResolved.Flags)) then
  6160. RaiseMsg(20170216152237,nIllegalQualifier,sIllegalQualifier,['as'],Bin);
  6161. if RightResolved.IdentEl=nil then
  6162. RaiseXExpectedButYFound(20170216152630,'class',RightResolved.TypeEl.ElementTypeName,Bin.right);
  6163. if not (RightResolved.IdentEl is TPasType) then
  6164. RaiseXExpectedButYFound(20170216152632,'class',RightResolved.IdentEl.Name,Bin.right);
  6165. if (CheckSrcIsADstType(RightResolved,LeftResolved,Bin)<>cIncompatible) then
  6166. begin
  6167. SetResolverValueExpr(ResolvedEl,btContext,RightResolved.TypeEl,Bin,[rrfReadable]);
  6168. exit;
  6169. end;
  6170. RaiseMsg(20170216152239,nTypesAreNotRelated,sTypesAreNotRelated,[],Bin);
  6171. end;
  6172. end;
  6173. eopLessThan,eopGreaterThan, eopLessthanEqual,eopGreaterThanEqual:
  6174. if (LeftResolved.TypeEl.ClassType=TPasEnumType)
  6175. and (rrfReadable in LeftResolved.Flags)
  6176. and (LeftResolved.TypeEl=RightResolved.TypeEl)
  6177. and (rrfReadable in RightResolved.Flags)
  6178. then
  6179. begin
  6180. SetBaseType(btBoolean);
  6181. exit;
  6182. end;
  6183. eopSubIdent:
  6184. begin
  6185. ResolvedEl:=RightResolved;
  6186. exit;
  6187. end;
  6188. end
  6189. else if LeftResolved.BaseType=btSet then
  6190. begin
  6191. if (rrfReadable in LeftResolved.Flags)
  6192. and (RightResolved.BaseType=btSet)
  6193. and (rrfReadable in RightResolved.Flags) then
  6194. case Bin.OpCode of
  6195. eopAdd,
  6196. eopSubtract,
  6197. eopMultiply,
  6198. eopSymmetricaldifference,
  6199. eopLessthanEqual,
  6200. eopGreaterThanEqual:
  6201. begin
  6202. if RightResolved.TypeEl=nil then
  6203. begin
  6204. // right is empty set
  6205. if Bin.OpCode in [eopLessthanEqual,eopGreaterThanEqual] then
  6206. SetBaseType(btBoolean)
  6207. else
  6208. begin
  6209. ResolvedEl:=LeftResolved;
  6210. ResolvedEl.IdentEl:=nil;
  6211. ResolvedEl.ExprEl:=Bin;
  6212. end;
  6213. exit;
  6214. end
  6215. else if LeftResolved.TypeEl=nil then
  6216. begin
  6217. // left is empty set
  6218. if Bin.OpCode in [eopLessthanEqual,eopGreaterThanEqual] then
  6219. SetBaseType(btBoolean)
  6220. else
  6221. begin
  6222. ResolvedEl:=RightResolved;
  6223. ResolvedEl.IdentEl:=nil;
  6224. ResolvedEl.ExprEl:=Bin;
  6225. end;
  6226. exit;
  6227. end
  6228. else if (LeftResolved.SubType=RightResolved.SubType)
  6229. or ((LeftResolved.SubType in btAllBooleans)
  6230. and (RightResolved.SubType in btAllBooleans))
  6231. or ((LeftResolved.SubType in btAllInteger)
  6232. and (RightResolved.SubType in btAllInteger)) then
  6233. begin
  6234. // compatible set
  6235. if Bin.OpCode in [eopLessthanEqual,eopGreaterThanEqual] then
  6236. SetBaseType(btBoolean)
  6237. else
  6238. begin
  6239. ResolvedEl:=LeftResolved;
  6240. ResolvedEl.IdentEl:=nil;
  6241. ResolvedEl.ExprEl:=Bin;
  6242. end;
  6243. exit;
  6244. end;
  6245. {$IFDEF VerbosePasResolver}
  6246. writeln('TPasResolver.ComputeBinaryExpr + - * >< Sets LeftSubType='+BaseTypeNames[LeftResolved.SubType]
  6247. +' RightSubType='+BaseTypeNames[RightResolved.SubType]);
  6248. {$ENDIF}
  6249. end;
  6250. end;
  6251. end
  6252. else if LeftResolved.BaseType=btModule then
  6253. begin
  6254. if Bin.OpCode=eopSubIdent then
  6255. begin
  6256. ResolvedEl:=RightResolved;
  6257. exit;
  6258. end;
  6259. end;
  6260. {$IFDEF VerbosePasResolver}
  6261. writeln('TPasResolver.ComputeBinaryExpr OpCode=',OpcodeStrings[Bin.OpCode],' Kind=',Bin.Kind,' Left=',GetResolverResultDbg(LeftResolved),' Right=',GetResolverResultDbg(RightResolved));
  6262. {$ENDIF}
  6263. RaiseMsg(20170216152241,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[Bin.OpCode]],Bin);
  6264. end;
  6265. procedure TPasResolver.ComputeArrayParams(Params: TParamsExpr; out
  6266. ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  6267. StartEl: TPasElement);
  6268. procedure ComputeIndexProperty(Prop: TPasProperty);
  6269. begin
  6270. if [rcConstant,rcType]*Flags<>[] then
  6271. RaiseConstantExprExp(20170216152635,Params);
  6272. ComputeElement(GetPasPropertyType(Prop),ResolvedEl,[rcType],StartEl);
  6273. ResolvedEl.IdentEl:=Prop;
  6274. ResolvedEl.Flags:=[];
  6275. if GetPasPropertyGetter(Prop)<>nil then
  6276. Include(ResolvedEl.Flags,rrfReadable);
  6277. if GetPasPropertySetter(Prop)<>nil then
  6278. Include(ResolvedEl.Flags,rrfWritable);
  6279. end;
  6280. var
  6281. TypeEl: TPasType;
  6282. ClassScope: TPasClassScope;
  6283. ArrayEl: TPasArrayType;
  6284. ArgNo: Integer;
  6285. OrigResolved: TPasResolverResult;
  6286. SubParams: TParamsExpr;
  6287. begin
  6288. if Params.Value.CustomData is TResolvedReference then
  6289. begin
  6290. // e.g. Name[]
  6291. ComputeElement(Params.Value,ResolvedEl,
  6292. Flags-[rcNoImplicitProc,rcNoImplicitProcType],StartEl);
  6293. end
  6294. else if Params.Value.ClassType=TParamsExpr then
  6295. begin
  6296. SubParams:=TParamsExpr(Params.Value);
  6297. if SubParams.Kind in [pekArrayParams,pekFuncParams] then
  6298. begin
  6299. // e.g. Name()[] or Name[][]
  6300. ComputeElement(SubParams,ResolvedEl,
  6301. Flags-[rcNoImplicitProc,rcNoImplicitProcType],StartEl);
  6302. end
  6303. else
  6304. RaiseNotYetImplemented(20161010195646,SubParams);
  6305. end
  6306. else
  6307. RaiseNotYetImplemented(20160928174144,Params);
  6308. {$IFDEF VerbosePasResolver}
  6309. writeln('TPasResolver.ComputeArrayParams ResolvedEl=',GetResolverResultDbg(ResolvedEl));
  6310. {$ENDIF}
  6311. if ResolvedEl.BaseType in btAllStrings then
  6312. begin
  6313. // stringvar[] => char
  6314. case GetActualBaseType(ResolvedEl.BaseType) of
  6315. btWideString,btUnicodeString:
  6316. if BaseTypeChar=btWideChar then
  6317. ResolvedEl.BaseType:=btChar
  6318. else
  6319. ResolvedEl.BaseType:=btWideChar;
  6320. btAnsiString,btRawByteString,btShortString:
  6321. if BaseTypeChar=btAnsiChar then
  6322. ResolvedEl.BaseType:=btChar
  6323. else
  6324. ResolvedEl.BaseType:=btAnsiChar;
  6325. else
  6326. RaiseNotYetImplemented(20170417202354,Params);
  6327. end;
  6328. // keep ResolvedEl.IdentEl the string var
  6329. ResolvedEl.TypeEl:=FBaseTypes[ResolvedEl.BaseType];
  6330. ResolvedEl.ExprEl:=Params;
  6331. ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable,rrfCanBeStatement]+[rrfAssignable];
  6332. end
  6333. else if (ResolvedEl.IdentEl is TPasProperty)
  6334. and (TPasProperty(ResolvedEl.IdentEl).Args.Count>0) then
  6335. // property with args
  6336. ComputeIndexProperty(TPasProperty(ResolvedEl.IdentEl))
  6337. else if ResolvedEl.BaseType=btContext then
  6338. begin
  6339. TypeEl:=ResolvedEl.TypeEl;
  6340. if TypeEl.ClassType=TPasClassType then
  6341. begin
  6342. ClassScope:=TypeEl.CustomData as TPasClassScope;
  6343. if ClassScope.DefaultProperty<>nil then
  6344. ComputeIndexProperty(ClassScope.DefaultProperty)
  6345. else
  6346. ComputeArrayParams_Class(Params,ResolvedEl,ClassScope,Flags,StartEl);
  6347. end
  6348. else if TypeEl.ClassType=TPasClassOfType then
  6349. begin
  6350. ClassScope:=TPasClassOfType(TypeEl).DestType.CustomData as TPasClassScope;
  6351. if ClassScope.DefaultProperty<>nil then
  6352. ComputeIndexProperty(ClassScope.DefaultProperty)
  6353. else
  6354. RaiseInternalError(20161010174916);
  6355. end
  6356. else if TypeEl.ClassType=TPasArrayType then
  6357. begin
  6358. if not (rrfReadable in ResolvedEl.Flags) then
  6359. RaiseMsg(20170517001140,nIllegalQualifier,sIllegalQualifier,['['],Params);
  6360. ArrayEl:=TPasArrayType(TypeEl);
  6361. ArgNo:=0;
  6362. repeat
  6363. if length(ArrayEl.Ranges)=0 then
  6364. begin
  6365. inc(ArgNo); // dynamic/open array has one dimension
  6366. if IsDynArray(ArrayEl) then
  6367. Include(ResolvedEl.Flags,rrfWritable); // dynamic array elements are writable
  6368. end
  6369. else
  6370. inc(ArgNo,length(ArrayEl.Ranges)); // static array has several dimensions
  6371. if ArgNo>length(Params.Params) then
  6372. RaiseInternalError(20161010185535);
  6373. if ArgNo=length(Params.Params) then
  6374. break;
  6375. // continue in sub array
  6376. ArrayEl:=ResolveAliasType(ArrayEl.ElType) as TPasArrayType;
  6377. until false;
  6378. OrigResolved:=ResolvedEl;
  6379. ComputeElement(ArrayEl.ElType,ResolvedEl,Flags,StartEl);
  6380. // identifier and value is the array itself
  6381. ResolvedEl.IdentEl:=OrigResolved.IdentEl;
  6382. ResolvedEl.ExprEl:=OrigResolved.ExprEl;
  6383. ResolvedEl.Flags:=OrigResolved.Flags*[rrfReadable,rrfWritable];
  6384. if IsDynArray(ArrayEl) then
  6385. // dyn array elements are writable independent of the array
  6386. Include(ResolvedEl.Flags,rrfWritable);
  6387. end
  6388. else
  6389. RaiseNotYetImplemented(20161010151727,Params,GetResolverResultDbg(ResolvedEl));
  6390. end
  6391. else
  6392. RaiseNotYetImplemented(20160928174212,Params,GetResolverResultDbg(ResolvedEl));
  6393. end;
  6394. procedure TPasResolver.ComputeArrayParams_Class(Params: TParamsExpr;
  6395. var ResolvedEl: TPasResolverResult; ClassScope: TPasClassScope;
  6396. Flags: TPasResolverComputeFlags; StartEl: TPasElement);
  6397. begin
  6398. RaiseInternalError(20161010174916);
  6399. if Params=nil then ;
  6400. if ClassScope=nil then ;
  6401. if Flags=[] then ;
  6402. if StartEl=nil then ;
  6403. SetResolverIdentifier(ResolvedEl,btNone,nil,nil,[]);
  6404. end;
  6405. procedure TPasResolver.ComputeFuncParams(Params: TParamsExpr; out
  6406. ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  6407. StartEl: TPasElement);
  6408. var
  6409. DeclEl: TPasElement;
  6410. BuiltInProc: TResElDataBuiltInProc;
  6411. Proc: TPasProcedure;
  6412. aClass: TPasClassType;
  6413. ResolvedTypeEl: TPasResolverResult;
  6414. Ref: TResolvedReference;
  6415. begin
  6416. if Params.Value.CustomData is TResolvedReference then
  6417. begin
  6418. Ref:=TResolvedReference(Params.Value.CustomData);
  6419. DeclEl:=Ref.Declaration;
  6420. if DeclEl.ClassType=TPasUnresolvedSymbolRef then
  6421. begin
  6422. if DeclEl.CustomData.ClassType=TResElDataBuiltInProc then
  6423. begin
  6424. BuiltInProc:=TResElDataBuiltInProc(DeclEl.CustomData);
  6425. if Assigned(BuiltInProc.GetCallResult) then
  6426. // built in function
  6427. BuiltInProc.GetCallResult(BuiltInProc,Params,ResolvedEl)
  6428. else
  6429. // built in procedure
  6430. SetResolverIdentifier(ResolvedEl,btProc,BuiltInProc.Proc,BuiltInProc.Proc,[]);
  6431. if bipfCanBeStatement in BuiltInProc.Flags then
  6432. Include(ResolvedEl.Flags,rrfCanBeStatement);
  6433. end
  6434. else if DeclEl.CustomData is TResElDataBaseType then
  6435. begin
  6436. // type cast to base type
  6437. if TResElDataBaseType(DeclEl.CustomData).BaseType=btCustom then
  6438. // custom base type
  6439. SetResolverValueExpr(ResolvedEl,
  6440. btCustom,
  6441. TPasUnresolvedSymbolRef(DeclEl),Params.Params[0],[rrfReadable])
  6442. else
  6443. SetResolverValueExpr(ResolvedEl,
  6444. TResElDataBaseType(DeclEl.CustomData).BaseType,
  6445. TPasUnresolvedSymbolRef(DeclEl),Params.Params[0],[rrfReadable]);
  6446. end
  6447. else
  6448. RaiseNotYetImplemented(20161006133040,Params,GetResolverResultDbg(ResolvedEl));
  6449. end
  6450. else
  6451. begin
  6452. // normal identifier (not built-in)
  6453. ComputeElement(DeclEl,ResolvedEl,Flags+[rcNoImplicitProc],StartEl);
  6454. if ResolvedEl.BaseType=btProc then
  6455. begin
  6456. if not (ResolvedEl.IdentEl is TPasProcedure) then
  6457. RaiseNotYetImplemented(20160928180201,Params,GetResolverResultDbg(ResolvedEl));
  6458. Proc:=TPasProcedure(ResolvedEl.IdentEl);
  6459. if rcConstant in Flags then
  6460. RaiseConstantExprExp(20170216152637,Params);
  6461. if Proc is TPasFunction then
  6462. // function call => return result
  6463. ComputeElement(TPasFunction(Proc).FuncType.ResultEl,ResolvedEl,
  6464. Flags+[rcNoImplicitProc],StartEl)
  6465. else if (Proc.ClassType=TPasConstructor)
  6466. and (rrfNewInstance in Ref.Flags) then
  6467. begin
  6468. // new instance call -> return value of type class
  6469. aClass:=GetReference_NewInstanceClass(Ref);
  6470. SetResolverValueExpr(ResolvedEl,btContext,aClass,Params.Value,[rrfReadable]);
  6471. end
  6472. else
  6473. // procedure call, result is neither readable nor writable
  6474. SetResolverIdentifier(ResolvedEl,btProc,Proc,Proc.ProcType,[]);
  6475. Include(ResolvedEl.Flags,rrfCanBeStatement);
  6476. end
  6477. else if ResolvedEl.TypeEl is TPasProcedureType then
  6478. begin
  6479. if Params.Value is TParamsExpr then
  6480. begin
  6481. // e.g. Name()() or Name[]()
  6482. Include(ResolvedEl.Flags,rrfReadable);
  6483. end;
  6484. if rrfReadable in ResolvedEl.Flags then
  6485. begin
  6486. // call procvar
  6487. if rcConstant in Flags then
  6488. RaiseConstantExprExp(20170216152639,Params);
  6489. if ResolvedEl.TypeEl is TPasFunctionType then
  6490. // function call => return result
  6491. ComputeElement(TPasFunctionType(ResolvedEl.TypeEl).ResultEl,
  6492. ResolvedEl,Flags+[rcNoImplicitProc],StartEl)
  6493. else
  6494. // procedure call, result is neither readable nor writable
  6495. SetResolverTypeExpr(ResolvedEl,btProc,TPasProcedureType(ResolvedEl.TypeEl),[]);
  6496. Include(ResolvedEl.Flags,rrfCanBeStatement);
  6497. end
  6498. else
  6499. begin
  6500. // typecast proctype
  6501. if length(Params.Params)<>1 then
  6502. begin
  6503. {$IFDEF VerbosePasResolver}
  6504. writeln('TPasResolver.ComputeFuncParams DeclEl=',GetObjName(DeclEl),' ',GetResolverResultDbg(ResolvedEl));
  6505. {$ENDIF}
  6506. RaiseMsg(20170416185211,nWrongNumberOfParametersForTypeCast,
  6507. sWrongNumberOfParametersForTypeCast,[ResolvedEl.TypeEl.Name],Params);
  6508. end;
  6509. SetResolverValueExpr(ResolvedEl,btContext,TPasProcedureType(ResolvedEl.TypeEl),
  6510. Params.Params[0],[rrfReadable]);
  6511. end;
  6512. end
  6513. else if (DeclEl is TPasType) then
  6514. begin
  6515. // type cast
  6516. ResolvedTypeEl:=ResolvedEl;
  6517. ComputeElement(Params.Params[0],ResolvedEl,Flags,StartEl);
  6518. ResolvedEl.BaseType:=ResolvedTypeEl.BaseType;
  6519. ResolvedEl.TypeEl:=ResolvedTypeEl.TypeEl;
  6520. end
  6521. else
  6522. RaiseNotYetImplemented(20160928180048,Params,GetResolverResultDbg(ResolvedEl));
  6523. end;
  6524. end
  6525. else
  6526. RaiseNotYetImplemented(20160928174124,Params);
  6527. end;
  6528. procedure TPasResolver.ComputeSetParams(Params: TParamsExpr; out
  6529. ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  6530. StartEl: TPasElement);
  6531. // [param,param,...]
  6532. var
  6533. ParamResolved, FirstResolved: TPasResolverResult;
  6534. i: Integer;
  6535. Param: TPasExpr;
  6536. IsRange: Boolean;
  6537. begin
  6538. if length(Params.Params)=0 then
  6539. SetResolverValueExpr(ResolvedEl,btSet,nil,Params,[rrfReadable])
  6540. else
  6541. begin
  6542. FirstResolved:=Default(TPasResolverResult);
  6543. Flags:=Flags-[rcNoImplicitProc,rcNoImplicitProcType];
  6544. for i:=0 to length(Params.Params)-1 do
  6545. begin
  6546. Param:=Params.Params[i];
  6547. ComputeElement(Params.Params[0],ParamResolved,Flags,StartEl);
  6548. if ParamResolved.BaseType=btSet then
  6549. RaiseNotYetImplemented(20170420134325,Param,'nested array literals');
  6550. IsRange:=ParamResolved.BaseType=btRange;
  6551. if IsRange then
  6552. ConvertRangeToFirstValue(ParamResolved);
  6553. if FirstResolved.BaseType=btNone then
  6554. begin
  6555. // first value -> check type usable in a set
  6556. FirstResolved:=ParamResolved;
  6557. if IsRange then
  6558. CheckIsOrdinal(FirstResolved,Param,true);
  6559. if rrfReadable in FirstResolved.Flags then
  6560. begin
  6561. // has a value
  6562. end
  6563. else
  6564. begin
  6565. if (FirstResolved.BaseType=btContext) then
  6566. begin
  6567. if FirstResolved.IdentEl is TPasClassType then
  6568. // array of classtypes
  6569. else
  6570. begin
  6571. {$IFDEF VerbosePasResolver}
  6572. writeln('TPasResolver.ComputeSetParams ',GetResolverResultDbg(FirstResolved));
  6573. {$ENDIF}
  6574. RaiseXExpectedButYFound(20170420002328,'array value','type',Param);
  6575. end;
  6576. end
  6577. else
  6578. begin
  6579. {$IFDEF VerbosePasResolver}
  6580. writeln('TPasResolver.ComputeSetParams ',GetResolverResultDbg(FirstResolved));
  6581. {$ENDIF}
  6582. RaiseXExpectedButYFound(20170420002332,'array value','type',Param);
  6583. end;
  6584. end;
  6585. end
  6586. else
  6587. begin
  6588. // next value
  6589. CombineArrayLitElTypes(Params.Params[0],Param,FirstResolved,ParamResolved);
  6590. end;
  6591. end;
  6592. FirstResolved.IdentEl:=nil;
  6593. if FirstResolved.ExprEl=nil then
  6594. FirstResolved.ExprEl:=Params;
  6595. FirstResolved.SubType:=FirstResolved.BaseType;
  6596. FirstResolved.BaseType:=btSet;
  6597. FirstResolved.Flags:=[rrfReadable];
  6598. ResolvedEl:=FirstResolved;
  6599. end;
  6600. end;
  6601. procedure TPasResolver.CheckIsClass(El: TPasElement;
  6602. const ResolvedEl: TPasResolverResult);
  6603. begin
  6604. if (ResolvedEl.BaseType<>btContext) then
  6605. RaiseMsg(20170216152245,nXExpectedButYFound,sXExpectedButYFound,
  6606. ['class',BaseTypeNames[ResolvedEl.BaseType]],El);
  6607. if (ResolvedEl.TypeEl.ClassType<>TPasClassType) then
  6608. RaiseMsg(20170216152246,nXExpectedButYFound,sXExpectedButYFound,
  6609. ['class',ResolvedEl.TypeEl.ElementTypeName],El);
  6610. end;
  6611. function TPasResolver.CheckTypeCastClassInstanceToClass(const FromClassRes,
  6612. ToClassRes: TPasResolverResult; ErrorEl: TPasElement): integer;
  6613. // called when type casting a class instance into an unrelated class
  6614. begin
  6615. if FromClassRes.BaseType=btNone then ;
  6616. if ToClassRes.BaseType=btNone then ;
  6617. if ErrorEl=nil then ;
  6618. Result:=cIncompatible;
  6619. end;
  6620. procedure TPasResolver.CheckSetLitElCompatible(Left, Right: TPasExpr;
  6621. const LHS, RHS: TPasResolverResult);
  6622. var
  6623. LBT, RBT: TResolverBaseType;
  6624. begin
  6625. // check both are values
  6626. if not (rrfReadable in LHS.Flags) then
  6627. begin
  6628. if LHS.TypeEl<>nil then
  6629. RaiseXExpectedButYFound(20170216152645,'ordinal',LHS.TypeEl.ElementTypeName,Left)
  6630. else
  6631. RaiseXExpectedButYFound(20170216152648,'ordinal',BaseTypeNames[LHS.BaseType],Left);
  6632. end;
  6633. if not (rrfReadable in RHS.Flags) then
  6634. begin
  6635. if RHS.TypeEl<>nil then
  6636. RaiseXExpectedButYFound(20170216152651,'ordinal',RHS.TypeEl.ElementTypeName,Right)
  6637. else
  6638. RaiseXExpectedButYFound(20170216152653,'ordinal',BaseTypeNames[RHS.BaseType],Right);
  6639. end;
  6640. // check both have the same ordinal type
  6641. LBT:=GetActualBaseType(LHS.BaseType);
  6642. RBT:=GetActualBaseType(RHS.BaseType);
  6643. if LBT in btAllBooleans then
  6644. begin
  6645. if RBT in btAllBooleans then
  6646. exit;
  6647. RaiseXExpectedButYFound(20170216152656,'boolean',BaseTypeNames[RHS.BaseType],Right);
  6648. end
  6649. else if LBT in btAllInteger then
  6650. begin
  6651. if RBT in btAllInteger then
  6652. exit;
  6653. RaiseXExpectedButYFound(20170216152658,'integer',BaseTypeNames[RHS.BaseType],Right);
  6654. end
  6655. else if LBT in btAllChars then
  6656. begin
  6657. if RBT in btAllChars then
  6658. exit;
  6659. RaiseXExpectedButYFound(20170216152702,'char',BaseTypeNames[RHS.BaseType],Right);
  6660. end
  6661. else if LBT=btContext then
  6662. begin
  6663. if LHS.TypeEl.ClassType=TPasEnumType then
  6664. begin
  6665. if LHS.TypeEl=RHS.TypeEl then
  6666. exit;
  6667. if RHS.TypeEl.ClassType<>TPasEnumType then
  6668. RaiseXExpectedButYFound(20170216152707,LHS.TypeEl.Parent.Name,RHS.TypeEl.ElementTypeName,Right);
  6669. if LHS.TypeEl.Parent<>RHS.TypeEl.Parent then
  6670. RaiseXExpectedButYFound(20170216152710,LHS.TypeEl.Parent.Name,RHS.TypeEl.Parent.Name,Right);
  6671. end
  6672. else
  6673. RaiseXExpectedButYFound(20170216152712,'ordinal',BaseTypeNames[LHS.BaseType],Left);
  6674. end
  6675. else
  6676. RaiseXExpectedButYFound(20170216152714,'ordinal',BaseTypeNames[LHS.BaseType],Left);
  6677. end;
  6678. function TPasResolver.CheckIsOrdinal(
  6679. const ResolvedEl: TPasResolverResult; ErrorEl: TPasElement;
  6680. RaiseOnError: boolean): boolean;
  6681. begin
  6682. Result:=false;
  6683. if ResolvedEl.BaseType in btAllRanges then
  6684. else if (ResolvedEl.BaseType=btContext) then
  6685. begin
  6686. if ResolvedEl.TypeEl.ClassType=TPasEnumType then
  6687. else if RaiseOnError then
  6688. RaiseXExpectedButYFound(20170216152718,'ordinal value',ResolvedEl.TypeEl.ElementTypeName,ErrorEl)
  6689. else
  6690. exit;
  6691. end
  6692. else if RaiseOnError then
  6693. RaiseXExpectedButYFound(20170216152720,'ordinal value',BaseTypeNames[ResolvedEl.BaseType],ErrorEl)
  6694. else
  6695. exit;
  6696. Result:=true;
  6697. end;
  6698. procedure TPasResolver.CombineArrayLitElTypes(Left, Right: TPasExpr;
  6699. var LHS: TPasResolverResult; const RHS: TPasResolverResult);
  6700. // LHS defines the array element type
  6701. // check if RHS
  6702. var
  6703. LBT, RBT: TResolverBaseType;
  6704. C: TClass;
  6705. begin
  6706. if LHS.TypeEl=nil then
  6707. RaiseXExpectedButYFound(20170420004537,'array element',BaseTypeNames[LHS.BaseType],Left);
  6708. if RHS.TypeEl=nil then
  6709. RaiseXExpectedButYFound(20170420004602,'array element',BaseTypeNames[RHS.BaseType],Right);
  6710. if LHS.TypeEl=RHS.TypeEl then
  6711. exit; // exact same type
  6712. LBT:=GetActualBaseType(LHS.BaseType);
  6713. RBT:=GetActualBaseType(RHS.BaseType);
  6714. if rrfReadable in LHS.Flags then
  6715. begin
  6716. if not (rrfReadable in RHS.Flags) then
  6717. RaiseIncompatibleTypeRes(20170420004759,nIncompatibleTypesGotExpected,
  6718. [],RHS,LHS,Right);
  6719. // array of values
  6720. if LBT in btAllBooleans then
  6721. begin
  6722. if RBT in btAllBooleans then
  6723. begin
  6724. LHS.BaseType:=GetCombinedBoolean(LBT,RBT,Right);
  6725. exit;
  6726. end;
  6727. RaiseXExpectedButYFound(20170420093015,'boolean',BaseTypeNames[RHS.BaseType],Right);
  6728. end
  6729. else if LBT in btAllInteger then
  6730. begin
  6731. if RBT in btAllInteger then
  6732. begin
  6733. LHS.BaseType:=GetCombinedInt(LHS,RHS,Right);
  6734. exit;
  6735. end;
  6736. RaiseXExpectedButYFound(20170420093019,'integer',BaseTypeNames[RHS.BaseType],Right);
  6737. end
  6738. else if LBT in btAllChars then
  6739. begin
  6740. if RBT in btAllChars then
  6741. begin
  6742. LHS.BaseType:=GetCombinedChar(LHS,RHS,Right);
  6743. exit;
  6744. end;
  6745. RaiseXExpectedButYFound(20170420093024,'char',BaseTypeNames[RHS.BaseType],Right);
  6746. end
  6747. else if LBT in btAllStrings then
  6748. begin
  6749. if RBT in btAllStringAndChars then
  6750. begin
  6751. LHS.BaseType:=GetCombinedString(LHS,RHS,Right);
  6752. exit;
  6753. end;
  6754. RaiseXExpectedButYFound(20170420102832,'string',BaseTypeNames[RHS.BaseType],Right);
  6755. end
  6756. else if LBT=btNil then
  6757. begin
  6758. if RBT=btNil then
  6759. exit
  6760. else if RBT=btPointer then
  6761. begin
  6762. LHS:=RHS;
  6763. exit;
  6764. end
  6765. else if RBT=btContext then
  6766. begin
  6767. C:=RHS.TypeEl.ClassType;
  6768. if (C=TPasClassType)
  6769. or (C=TPasClassOfType)
  6770. or (C=TPasPointerType)
  6771. or ((C=TPasArrayType) and IsDynArray(RHS.TypeEl))
  6772. or (C=TPasProcedureType)
  6773. or (C=TPasFunctionType) then
  6774. begin
  6775. LHS:=RHS;
  6776. exit;
  6777. end;
  6778. end;
  6779. end
  6780. else if LBT=btContext then
  6781. begin
  6782. C:=LHS.TypeEl.ClassType;
  6783. if C=TPasEnumType then
  6784. begin
  6785. if LHS.TypeEl=RHS.TypeEl then
  6786. exit;
  6787. end
  6788. else if C=TPasClassType then
  6789. begin
  6790. // array of class instances
  6791. if RHS.TypeEl.ClassType<>TPasClassType then
  6792. RaiseIncompatibleTypeRes(20170420135637,nIncompatibleTypesGotExpected,
  6793. [],RHS,LHS,Right);
  6794. if CheckClassIsClass(LHS.TypeEl,RHS.TypeEl,Right)<cIncompatible then
  6795. begin
  6796. // right class type is a left class type -> ok
  6797. exit;
  6798. end
  6799. else if CheckClassIsClass(RHS.TypeEl,LHS.TypeEl,Right)<cIncompatible then
  6800. begin
  6801. // left class type is a right class type -> right is the new base class type
  6802. LHS:=RHS;
  6803. exit;
  6804. end;
  6805. end;
  6806. end;
  6807. end
  6808. else
  6809. begin
  6810. // array of types
  6811. if rrfReadable in RHS.Flags then
  6812. RaiseIncompatibleTypeRes(20170420004925,nIncompatibleTypesGotExpected,
  6813. [],RHS,LHS,Right);
  6814. if LBT=btContext then
  6815. begin
  6816. if LHS.TypeEl.ClassType=TPasClassType then
  6817. begin
  6818. // array of class type
  6819. if RHS.TypeEl.ClassType<>TPasClassType then
  6820. RaiseIncompatibleTypeRes(20170420091839,nIncompatibleTypesGotExpected,
  6821. [],RHS,LHS,Right);
  6822. if CheckClassIsClass(LHS.TypeEl,RHS.TypeEl,Right)<cIncompatible then
  6823. begin
  6824. // right class type is a left class type -> ok
  6825. exit;
  6826. end
  6827. else if CheckClassIsClass(RHS.TypeEl,LHS.TypeEl,Right)<cIncompatible then
  6828. begin
  6829. // left class type is a right class type -> right is the new base class type
  6830. LHS:=RHS;
  6831. exit;
  6832. end;
  6833. end;
  6834. end;
  6835. end;
  6836. RaiseIncompatibleTypeRes(20170420092625,nIncompatibleTypesGotExpected,
  6837. [],RHS,LHS,Right);
  6838. end;
  6839. procedure TPasResolver.ConvertRangeToFirstValue(
  6840. var ResolvedEl: TPasResolverResult);
  6841. begin
  6842. if ResolvedEl.BaseType<>btRange then
  6843. RaiseInternalError(20161001155732);
  6844. if ResolvedEl.TypeEl=nil then
  6845. if ResolvedEl.IdentEl<>nil then
  6846. RaiseNotYetImplemented(20161001155747,ResolvedEl.IdentEl)
  6847. else
  6848. RaiseNotYetImplemented(20161001155834,ResolvedEl.ExprEl);
  6849. ResolvedEl.BaseType:=ResolvedEl.SubType;
  6850. ResolvedEl.SubType:=btNone;
  6851. end;
  6852. function TPasResolver.IsCharLiteral(const Value: string; ErrorPos: TPasElement
  6853. ): TResolverBaseType;
  6854. // returns true if Value is a Pascal char literal
  6855. // btChar: #65, #$50, ^G, 'a'
  6856. // btWideChar: #10000, 'ä'
  6857. var
  6858. p: PChar;
  6859. i: SizeInt;
  6860. base: Integer;
  6861. begin
  6862. Result:=btNone;
  6863. //writeln('TPasResolver.IsCharLiteral ',BaseTypeChar,' "',Value,'" l=',length(Value));
  6864. p:=PChar(Value);
  6865. case p^ of
  6866. '''':
  6867. begin
  6868. inc(p);
  6869. case p^ of
  6870. '''':
  6871. if (p[1]='''') and (p[2]='''') and (p[3]=#0) then
  6872. Result:=btChar;
  6873. #32..#38,#40..#191:
  6874. if (p[1]='''') and (p[2]=#0) then
  6875. Result:=btChar;
  6876. #192..#255:
  6877. if BaseTypeChar=btWideChar then
  6878. begin
  6879. // default char is widechar: UTF-8 'ä' is a widechar
  6880. i:=Utf8CodePointLen(p,4,false);
  6881. //writeln('TPasResolver.IsCharLiteral "',Value,'" ',length(Value),' i=',i);
  6882. if i<2 then
  6883. exit;
  6884. inc(p,i);
  6885. if (p^='''') and (p[1]=#0) then
  6886. // single UTF-8 codepoint
  6887. Result:=btWideChar;
  6888. end;
  6889. end;
  6890. end;
  6891. '#':
  6892. begin
  6893. inc(p);
  6894. case p^ of
  6895. '$': begin base:=16; inc(p); end;
  6896. '&': begin base:=8; inc(p); end;
  6897. '%': begin base:=2; inc(p); end;
  6898. '0'..'9': base:=10;
  6899. else RaiseNotYetImplemented(20170728142709,ErrorPos);
  6900. end;
  6901. i:=0;
  6902. repeat
  6903. case p^ of
  6904. '0'..'9': i:=i*base+ord(p^)-ord('0');
  6905. 'A'..'Z': i:=i*base+ord(p^)-ord('A')+10;
  6906. 'a'..'z': i:=i*base+ord(p^)-ord('a')+10;
  6907. else
  6908. break;
  6909. end;
  6910. inc(p);
  6911. until false;
  6912. if p^=#0 then
  6913. if i<256 then
  6914. Result:=btChar
  6915. else
  6916. Result:=btWideChar;
  6917. end;
  6918. '^':
  6919. begin
  6920. inc(p);
  6921. if (p^ in ['a'..'z','A'..'Z']) and (p[1]=#0) then
  6922. exit(btChar);
  6923. end;
  6924. end;
  6925. end;
  6926. function TPasResolver.CheckBuiltInMinParamCount(Proc: TResElDataBuiltInProc;
  6927. Expr: TPasExpr; MinCount: integer; RaiseOnError: boolean): boolean;
  6928. begin
  6929. if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)<MinCount) then
  6930. begin
  6931. if RaiseOnError then
  6932. RaiseMsg(20170216152248,nWrongNumberOfParametersForCallTo,
  6933. sWrongNumberOfParametersForCallTo,[Proc.Signature],Expr);
  6934. exit(false);
  6935. end;
  6936. Result:=true;
  6937. end;
  6938. function TPasResolver.CheckBuiltInMaxParamCount(Proc: TResElDataBuiltInProc;
  6939. Params: TParamsExpr; MaxCount: integer; RaiseOnError: boolean): integer;
  6940. begin
  6941. if length(Params.Params)>MaxCount then
  6942. begin
  6943. if RaiseOnError then
  6944. RaiseMsg(20170329154348,nWrongNumberOfParametersForCallTo,
  6945. sWrongNumberOfParametersForCallTo,[Proc.Signature],Params.Params[MaxCount]);
  6946. exit(cIncompatible);
  6947. end;
  6948. Result:=cExact;
  6949. end;
  6950. function TPasResolver.CheckRaiseTypeArgNo(id: int64; ArgNo: integer;
  6951. Param: TPasExpr; const ParamResolved: TPasResolverResult; Expected: string;
  6952. RaiseOnError: boolean): integer;
  6953. begin
  6954. if RaiseOnError then
  6955. RaiseMsg(id,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  6956. [IntToStr(ArgNo),GetResolverResultDescription(ParamResolved,true),Expected],Param);
  6957. Result:=cIncompatible;
  6958. end;
  6959. procedure TPasResolver.OnExprEvalLog(Sender: TResExprEvaluator;
  6960. const id: int64; MsgType: TMessageType; MsgNumber: integer;
  6961. const Fmt: String; Args: array of const; PosEl: TPasElement);
  6962. begin
  6963. if MsgType<=mtError then
  6964. RaiseMsg(id,MsgNumber,Fmt,Args,PosEl)
  6965. else
  6966. LogMsg(id,MsgType,MsgNumber,Fmt,Args,PosEl);
  6967. if Sender=nil then ;
  6968. end;
  6969. function TPasResolver.OnExprEvalIdentifier(Sender: TResExprEvaluator;
  6970. Expr: TPrimitiveExpr; Flags: TResEvalFlags): TResEvalValue;
  6971. var
  6972. Ref: TResolvedReference;
  6973. Decl: TPasElement;
  6974. C: TClass;
  6975. BaseTypeData: TResElDataBaseType;
  6976. ResolvedType: TPasResolverResult;
  6977. EnumValue: TPasEnumValue;
  6978. EnumType: TPasEnumType;
  6979. begin
  6980. Result:=nil;
  6981. if not (Expr.CustomData is TResolvedReference) then
  6982. RaiseNotYetImplemented(20170518203134,Expr);
  6983. Ref:=TResolvedReference(Expr.CustomData);
  6984. Decl:=Ref.Declaration;
  6985. {$IFDEF VerbosePasResEval}
  6986. writeln('TPasResolver.OnExprEvalIdentifier Value=',Expr.Value,' Decl=',GetObjName(Decl));
  6987. {$ENDIF}
  6988. C:=Decl.ClassType;
  6989. if C=TPasConst then
  6990. begin
  6991. if (TPasConst(Decl).Expr<>nil)
  6992. and (TPasConst(Decl).IsConst or (TPasConst(Decl).VarType=nil)) then
  6993. begin
  6994. if TPasConst(Decl).VarType<>nil then
  6995. begin
  6996. // typed const
  6997. ComputeElement(TPasConst(Decl).VarType,ResolvedType,[rcType]);
  6998. end
  6999. else
  7000. ResolvedType.BaseType:=btNone;
  7001. Result:=fExprEvaluator.Eval(TPasConst(Decl).Expr,Flags+[refConst]);
  7002. if Result<>nil then
  7003. begin
  7004. if (Result.Element<>nil) and (Result.Element<>TPasConst(Decl).Expr) then
  7005. Result:=Result.Clone;
  7006. Result.IdentEl:=Decl;
  7007. if TPasConst(Decl).VarType<>nil then
  7008. begin
  7009. // typed const
  7010. if Result.Kind=revkInt then
  7011. case ResolvedType.BaseType of
  7012. btByte: TResEvalInt(Result).Typed:=reitByte;
  7013. btShortInt: TResEvalInt(Result).Typed:=reitShortInt;
  7014. btWord: TResEvalInt(Result).Typed:=reitWord;
  7015. btSmallInt: TResEvalInt(Result).Typed:=reitSmallInt;
  7016. btUIntSingle: TResEvalInt(Result).Typed:=reitUIntSingle;
  7017. btIntSingle: TResEvalInt(Result).Typed:=reitIntSingle;
  7018. btLongWord: TResEvalInt(Result).Typed:=reitLongWord;
  7019. btLongint: TResEvalInt(Result).Typed:=reitLongInt;
  7020. btUIntDouble: TResEvalInt(Result).Typed:=reitUIntDouble;
  7021. btIntDouble: TResEvalInt(Result).Typed:=reitIntDouble;
  7022. btInt64: TResEvalInt(Result).Typed:=reitNone; // default
  7023. else
  7024. ReleaseEvalValue(Result);
  7025. RaiseNotYetImplemented(20170624181050,TPasConst(Decl).VarType);
  7026. end;
  7027. end;
  7028. exit;
  7029. end;
  7030. end;
  7031. if refConst in Flags then
  7032. RaiseConstantExprExp(20170518214928,Expr);
  7033. end
  7034. else if C=TPasEnumValue then
  7035. begin
  7036. EnumValue:=TPasEnumValue(Decl);
  7037. EnumType:=EnumValue.Parent as TPasEnumType;
  7038. Result:=TResEvalEnum.CreateValue(EnumType.Values.IndexOf(EnumValue),EnumValue);
  7039. exit;
  7040. end
  7041. else if C.InheritsFrom(TPasType) then
  7042. begin
  7043. Decl:=ResolveAliasType(TPasType(Decl));
  7044. C:=Decl.ClassType;
  7045. if C=TPasRangeType then
  7046. begin
  7047. Result:=fExprEvaluator.Eval(TPasRangeType(Decl).RangeExpr,Flags);
  7048. if Result<>nil then
  7049. begin
  7050. Result.IdentEl:=Ref.Declaration;
  7051. exit;
  7052. end;
  7053. end
  7054. else if C=TPasEnumType then
  7055. begin
  7056. Result:=TResEvalRangeInt.CreateValue(revskEnum,TPasEnumType(Decl),
  7057. 0,TPasEnumType(Decl).Values.Count-1);
  7058. Result.IdentEl:=Decl;
  7059. exit;
  7060. end
  7061. else if C=TPasUnresolvedSymbolRef then
  7062. begin
  7063. if (Decl.CustomData is TResElDataBaseType) then
  7064. begin
  7065. BaseTypeData:=TResElDataBaseType(Decl.CustomData);
  7066. case BaseTypeData.BaseType of
  7067. btChar:
  7068. begin
  7069. Result:=TResEvalRangeInt.Create;
  7070. TResEvalRangeInt(Result).ElKind:=revskChar;
  7071. TResEvalRangeInt(Result).RangeStart:=0;
  7072. if BaseTypeChar in [btChar,btAnsiChar] then
  7073. TResEvalRangeInt(Result).RangeEnd:=$ff
  7074. else
  7075. TResEvalRangeInt(Result).RangeEnd:=$ffff;
  7076. end;
  7077. btAnsiChar:
  7078. Result:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ff);
  7079. btWideChar:
  7080. Result:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ffff);
  7081. btBoolean,btByteBool,btWordBool,btQWordBool:
  7082. Result:=TResEvalRangeInt.CreateValue(revskBool,nil,0,1);
  7083. btByte,
  7084. btShortInt,
  7085. btWord,
  7086. btSmallInt,
  7087. btLongWord,
  7088. btLongint,
  7089. btInt64,
  7090. btComp,
  7091. btIntSingle,
  7092. btUIntSingle,
  7093. btIntDouble,
  7094. btUIntDouble:
  7095. begin
  7096. Result:=TResEvalRangeInt.Create;
  7097. TResEvalRangeInt(Result).ElKind:=revskInt;
  7098. GetIntegerRange(BaseTypeData.BaseType,
  7099. TResEvalRangeInt(Result).RangeStart,TResEvalRangeInt(Result).RangeEnd);
  7100. exit;
  7101. end;
  7102. end;
  7103. end;
  7104. end;
  7105. end;
  7106. {$IFDEF VerbosePasResEval}
  7107. writeln('TPasResolver.OnExprEvalIdentifier END Result=',dbgs(Result),' refConst=',refConst in Flags);
  7108. {$ENDIF}
  7109. if refConst in Flags then
  7110. RaiseConstantExprExp(20170518213616,Expr);
  7111. end;
  7112. function TPasResolver.OnExprEvalParams(Sender: TResExprEvaluator;
  7113. Params: TParamsExpr; Flags: TResEvalFlags): TResEvalValue;
  7114. var
  7115. Ref: TResolvedReference;
  7116. Decl: TPasElement;
  7117. C: TClass;
  7118. BuiltInProc: TResElDataBuiltInProc;
  7119. bt: TResolverBaseType;
  7120. begin
  7121. Result:=nil;
  7122. case Params.Kind of
  7123. pekArrayParams: ;
  7124. pekFuncParams:
  7125. if Params.Value.CustomData is TResolvedReference then
  7126. begin
  7127. Ref:=TResolvedReference(Params.Value.CustomData);
  7128. Decl:=Ref.Declaration;
  7129. if Decl is TPasType then
  7130. Decl:=ResolveAliasType(TPasType(Decl));
  7131. C:=Decl.ClassType;
  7132. if C=TPasUnresolvedSymbolRef then
  7133. begin
  7134. if Decl.CustomData is TResElDataBuiltInProc then
  7135. begin
  7136. BuiltInProc:=TResElDataBuiltInProc(Decl.CustomData);
  7137. {$IFDEF VerbosePasResEval}
  7138. writeln('TPasResolver.OnExprEvalParams Calling BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
  7139. {$ENDIF}
  7140. case BuiltInProc.BuiltIn of
  7141. bfLength: BI_Length_OnEval(BuiltInProc,Params,Flags,Result);
  7142. bfAssigned: Result:=nil;
  7143. bfChr: BI_Chr_OnEval(BuiltInProc,Params,Flags,Result);
  7144. bfOrd: BI_Ord_OnEval(BuiltInProc,Params,Flags,Result);
  7145. bfLow,bfHigh: BI_LowHigh_OnEval(BuiltInProc,Params,Flags,Result);
  7146. bfPred,bfSucc: BI_PredSucc_OnEval(BuiltInProc,Params,Flags,Result);
  7147. bfStrFunc: BI_StrFunc_OnEval(BuiltInProc,Params,Flags,Result);
  7148. bfConcatArray: Result:=nil;
  7149. bfCopyArray: Result:=nil;
  7150. bfTypeInfo: Result:=nil;
  7151. else
  7152. {$IFDEF VerbosePasResEval}
  7153. writeln('TPasResolver.OnExprEvalParams Unhandled BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn]);
  7154. {$ENDIF}
  7155. RaiseNotYetImplemented(20170624192324,Params);
  7156. end;
  7157. {$IFDEF VerbosePasResEval}
  7158. if Result<>nil then
  7159. writeln('TPasResolver.OnExprEvalParams Called BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn],' Result=',Result.AsString)
  7160. else
  7161. writeln('TPasResolver.OnExprEvalParams Called BuiltInProc ',Decl.Name,' ',ResolverBuiltInProcNames[BuiltInProc.BuiltIn],' Result=nil');
  7162. {$ENDIF}
  7163. exit;
  7164. end
  7165. else if Decl.CustomData is TResElDataBaseType then
  7166. begin
  7167. // typecast to basetype
  7168. bt:=TResElDataBaseType(Decl.CustomData).BaseType;
  7169. Result:=EvalBaseTypeCast(Params,bt);
  7170. end;
  7171. {$IFDEF VerbosePasResEval}
  7172. writeln('TPasResolver.OnExprEvalParams BuiltInProc ',Decl.Name,' ',GetObjName(Decl.CustomData));
  7173. {$ENDIF}
  7174. end
  7175. else if C=TPasEnumType then
  7176. begin
  7177. // typecast to enumtype
  7178. Result:=fExprEvaluator.EnumTypeCast(TPasEnumType(Decl),Params.Params[0],Flags);
  7179. end;
  7180. end;
  7181. pekSet: ;
  7182. end;
  7183. if Flags=[] then ;
  7184. end;
  7185. function TPasResolver.EvalBaseTypeCast(Params: TParamsExpr;
  7186. bt: TResolverBaseType): TResEvalvalue;
  7187. var
  7188. Value: TResEvalValue;
  7189. Int: MaxPrecInt;
  7190. MinIntVal, MaxIntVal: int64;
  7191. Flo: MaxPrecFloat;
  7192. begin
  7193. Result:=nil;
  7194. {$IFDEF VerbosePasResEval}
  7195. writeln('TPasResolver.EvalBaseTypeCast bt=',bt);
  7196. {$ENDIF}
  7197. Value:=Eval(Params.Params[0],[refAutoConst]);
  7198. if Value=nil then exit;
  7199. try
  7200. case Value.Kind of
  7201. revkInt:
  7202. begin
  7203. Int:=TResEvalInt(Value).Int;
  7204. if bt=btQWord then
  7205. begin
  7206. // int to qword
  7207. {$R-}
  7208. Result:=TResEvalUInt.CreateValue(MaxPrecUInt(Int));
  7209. {$IFDEF RangeCheckOn}{$R+}{$ENDIF}
  7210. end
  7211. else if bt in (btAllInteger-[btQWord]) then
  7212. begin
  7213. // int to int
  7214. GetIntegerRange(bt,MinIntVal,MaxIntVal);
  7215. if (Int<MinIntVal) or (Int>MaxIntVal) then
  7216. begin
  7217. {$R-}
  7218. case bt of
  7219. btByte: Result:=TResEvalInt.CreateValue(byte(Int),reitByte);
  7220. btShortInt: Result:=TResEvalInt.CreateValue(shortint(Int),reitShortInt);
  7221. btWord: Result:=TResEvalInt.CreateValue(word(Int),reitWord);
  7222. btSmallInt: Result:=TResEvalInt.CreateValue(smallint(Int),reitSmallInt);
  7223. btLongWord: Result:=TResEvalInt.CreateValue(longword(Int),reitLongWord);
  7224. btLongint: Result:=TResEvalInt.CreateValue(longint(Int),reitLongInt);
  7225. btInt64: Result:=TResEvalInt.CreateValue(Int);
  7226. btUIntSingle,
  7227. btIntSingle,
  7228. btUIntDouble,
  7229. btIntDouble:
  7230. fExprEvaluator.EmitRangeCheckConst(20170624194534,
  7231. Value.AsString,MinIntVal,MaxIntVal,Params,mtError);
  7232. else
  7233. RaiseNotYetImplemented(20170624200109,Params);
  7234. end;
  7235. {$IFDEF RangeCheckOn}{$R+}{$ENDIF}
  7236. end
  7237. else
  7238. begin
  7239. {$R-}
  7240. case bt of
  7241. btByte: Result:=TResEvalInt.CreateValue(Int,reitByte);
  7242. btShortInt: Result:=TResEvalInt.CreateValue(Int,reitShortInt);
  7243. btWord: Result:=TResEvalInt.CreateValue(Int,reitWord);
  7244. btSmallInt: Result:=TResEvalInt.CreateValue(Int,reitSmallInt);
  7245. btUIntSingle: Result:=TResEvalInt.CreateValue(Int,reitUIntSingle);
  7246. btIntSingle: Result:=TResEvalInt.CreateValue(Int,reitIntSingle);
  7247. btLongWord: Result:=TResEvalInt.CreateValue(Int,reitLongWord);
  7248. btLongint: Result:=TResEvalInt.CreateValue(Int,reitLongInt);
  7249. btUIntDouble: Result:=TResEvalInt.CreateValue(Int,reitUIntDouble);
  7250. btIntDouble: Result:=TResEvalInt.CreateValue(Int,reitIntDouble);
  7251. btInt64: Result:=TResEvalInt.CreateValue(Int);
  7252. else
  7253. RaiseNotYetImplemented(20170624200109,Params);
  7254. end;
  7255. {$IFDEF RangeCheckOn}{$R+}{$ENDIF}
  7256. end;
  7257. exit;
  7258. end
  7259. else if bt=btboolean then
  7260. case Int of
  7261. 0: Result:=TResEvalBool.CreateValue(false);
  7262. 1: Result:=TResEvalBool.CreateValue(true);
  7263. else
  7264. fExprEvaluator.EmitRangeCheckConst(20170710203254,
  7265. Value.AsString,0,1,Params,mtError);
  7266. end
  7267. else if bt=btSingle then
  7268. try
  7269. Result:=TResEvalFloat.CreateValue(Single(Int))
  7270. except
  7271. RaiseMsg(20170711002015,nRangeCheckError,sRangeCheckError,[],Params);
  7272. end
  7273. else if bt=btDouble then
  7274. try
  7275. Result:=TResEvalFloat.CreateValue(Double(Int))
  7276. except
  7277. RaiseMsg(20170711002016,nRangeCheckError,sRangeCheckError,[],Params);
  7278. end
  7279. else
  7280. begin
  7281. {$IFDEF VerbosePasResEval}
  7282. writeln('TPasResolver.OnExprEvalParams typecast int to ',bt);
  7283. {$ENDIF}
  7284. RaiseNotYetImplemented(20170624194308,Params);
  7285. end;
  7286. end;
  7287. revkFloat:
  7288. begin
  7289. Flo:=TResEvalFloat(Value).FloatValue;
  7290. if bt in (btAllInteger-[btQWord]) then
  7291. begin
  7292. // float to int
  7293. GetIntegerRange(bt,MinIntVal,MaxIntVal);
  7294. if (Flo<MinIntVal) or (Flo>MaxIntVal) then
  7295. fExprEvaluator.EmitRangeCheckConst(20170711001228,
  7296. Value.AsString,MinIntVal,MaxIntVal,Params,mtError);
  7297. {$R-}
  7298. try
  7299. Int:=Round(Flo);
  7300. except
  7301. RaiseMsg(20170711002218,nRangeCheckError,sRangeCheckError,[],Params);
  7302. end;
  7303. case bt of
  7304. btByte: Result:=TResEvalInt.CreateValue(Int,reitByte);
  7305. btShortInt: Result:=TResEvalInt.CreateValue(Int,reitShortInt);
  7306. btWord: Result:=TResEvalInt.CreateValue(Int,reitWord);
  7307. btSmallInt: Result:=TResEvalInt.CreateValue(Int,reitSmallInt);
  7308. btUIntSingle: Result:=TResEvalInt.CreateValue(Int,reitUIntSingle);
  7309. btIntSingle: Result:=TResEvalInt.CreateValue(Int,reitIntSingle);
  7310. btLongWord: Result:=TResEvalInt.CreateValue(Int,reitLongWord);
  7311. btLongint: Result:=TResEvalInt.CreateValue(Int,reitLongInt);
  7312. btUIntDouble: Result:=TResEvalInt.CreateValue(Int,reitUIntDouble);
  7313. btIntDouble: Result:=TResEvalInt.CreateValue(Int,reitIntDouble);
  7314. btInt64: Result:=TResEvalInt.CreateValue(Int);
  7315. else
  7316. RaiseNotYetImplemented(20170711001513,Params);
  7317. end;
  7318. {$IFDEF RangeCheckOn}{$R+}{$ENDIF}
  7319. exit;
  7320. end
  7321. else if bt=btSingle then
  7322. begin
  7323. // float to single
  7324. try
  7325. Result:=TResEvalFloat.CreateValue(single(Flo));
  7326. except
  7327. RaiseMsg(20170711002315,nRangeCheckError,sRangeCheckError,[],Params);
  7328. end;
  7329. end
  7330. else if bt=btDouble then
  7331. begin
  7332. // float to double
  7333. try
  7334. Result:=TResEvalFloat.CreateValue(double(Flo));
  7335. except
  7336. RaiseMsg(20170711002327,nRangeCheckError,sRangeCheckError,[],Params);
  7337. end;
  7338. end
  7339. else
  7340. begin
  7341. {$IFDEF VerbosePasResEval}
  7342. writeln('TPasResolver.OnExprEvalParams typecast float to ',bt);
  7343. {$ENDIF}
  7344. RaiseNotYetImplemented(20170711002542,Params);
  7345. end;
  7346. end
  7347. else
  7348. {$IFDEF VerbosePasResEval}
  7349. writeln('TPasResolver.OnExprEvalParams typecast to ',bt);
  7350. {$ENDIF}
  7351. RaiseNotYetImplemented(20170624193436,Params);
  7352. end;
  7353. finally
  7354. ReleaseEvalValue(Value);
  7355. end;
  7356. end;
  7357. function TPasResolver.Eval(Expr: TPasExpr; Flags: TResEvalFlags;
  7358. Store: boolean): TResEvalValue;
  7359. // Important: Caller must free result with ReleaseEvalValue(Result)
  7360. begin
  7361. Result:=fExprEvaluator.Eval(Expr,Flags);
  7362. if Result=nil then exit;
  7363. {$IFDEF VerbosePasResEval}
  7364. writeln('TPasResolver.Eval Result=',Result.AsDebugString);
  7365. {$ENDIF}
  7366. if Store
  7367. and (Expr.CustomData=nil)
  7368. and (Result.Element=nil)
  7369. and (not fExprEvaluator.IsSimpleExpr(Expr)) then
  7370. AddResolveData(Expr,Result,lkModule);
  7371. end;
  7372. function TPasResolver.CheckAssignCompatibilityCustom(const LHS,
  7373. RHS: TPasResolverResult; ErrorEl: TPasElement; RaiseOnIncompatible: boolean;
  7374. var Handled: boolean): integer;
  7375. // called when LHS or RHS BaseType is btCustom
  7376. // if RaiseOnIncompatible=true you can raise an useful error.
  7377. begin
  7378. Result:=cIncompatible;
  7379. if LHS.BaseType=btNone then ;
  7380. if RHS.BaseType=btNone then ;
  7381. if ErrorEl=nil then ;
  7382. if RaiseOnIncompatible then ;
  7383. if Handled then ;
  7384. end;
  7385. function TPasResolver.CheckEqualCompatibilityCustomType(const LHS,
  7386. RHS: TPasResolverResult; ErrorEl: TPasElement; RaiseOnIncompatible: boolean
  7387. ): integer;
  7388. begin
  7389. Result:=cIncompatible;
  7390. if LHS.BaseType=RHS.BaseType then;
  7391. if ErrorEl=nil then;
  7392. if RaiseOnIncompatible then ;
  7393. end;
  7394. function TPasResolver.BI_Length_OnGetCallCompatibility(
  7395. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7396. // check params of built in proc 'length'
  7397. var
  7398. Params: TParamsExpr;
  7399. Param: TPasExpr;
  7400. ParamResolved: TPasResolverResult;
  7401. Ranges: TPasExprArray;
  7402. begin
  7403. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  7404. exit(cIncompatible);
  7405. Params:=TParamsExpr(Expr);
  7406. // first param: string or dynamic array
  7407. Param:=Params.Params[0];
  7408. ComputeElement(Param,ParamResolved,[]);
  7409. Result:=cIncompatible;
  7410. if rrfReadable in ParamResolved.Flags then
  7411. begin
  7412. if ParamResolved.BaseType in btAllStringAndChars then
  7413. Result:=cExact
  7414. else if ParamResolved.BaseType=btContext then
  7415. begin
  7416. if (ParamResolved.TypeEl.ClassType=TPasArrayType) then
  7417. begin
  7418. Ranges:=TPasArrayType(ParamResolved.TypeEl).Ranges;
  7419. if length(Ranges)=0 then
  7420. Result:=cExact;
  7421. end;
  7422. end;
  7423. end;
  7424. if Result=cIncompatible then
  7425. exit(CheckRaiseTypeArgNo(20170329160335,1,Param,ParamResolved,
  7426. 'string or dynamic array',RaiseOnError));
  7427. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  7428. end;
  7429. procedure TPasResolver.BI_Length_OnGetCallResult(Proc: TResElDataBuiltInProc;
  7430. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  7431. begin
  7432. if Params=nil then ;
  7433. SetResolverIdentifier(ResolvedEl,BaseTypeLength,Proc.Proc,
  7434. FBaseTypes[BaseTypeLength],[rrfReadable]);
  7435. end;
  7436. procedure TPasResolver.BI_Length_OnEval(Proc: TResElDataBuiltInProc;
  7437. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
  7438. var
  7439. Value: TResEvalValue;
  7440. begin
  7441. Evaluated:=nil;
  7442. Value:=Eval(Params.Params[0],Flags);
  7443. if Value=nil then exit;
  7444. case Value.Kind of
  7445. revkString:
  7446. Evaluated:=TResEvalInt.CreateValue(length(TResEvalString(Value).S));
  7447. revkUnicodeString:
  7448. Evaluated:=TResEvalInt.CreateValue(length(TResEvalUTF16(Value).S));
  7449. end;
  7450. ReleaseEvalValue(Value);
  7451. if Proc=nil then ;
  7452. end;
  7453. function TPasResolver.BI_SetLength_OnGetCallCompatibility(
  7454. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7455. // check params of built in proc 'setlength'
  7456. var
  7457. Params: TParamsExpr;
  7458. Param: TPasExpr;
  7459. ParamResolved: TPasResolverResult;
  7460. begin
  7461. if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
  7462. exit(cIncompatible);
  7463. Params:=TParamsExpr(Expr);
  7464. // first param: string or array variable
  7465. Param:=Params.Params[0];
  7466. ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
  7467. Result:=cIncompatible;
  7468. if ResolvedElCanBeVarParam(ParamResolved) then
  7469. begin
  7470. if ParamResolved.BaseType in btAllStrings then
  7471. Result:=cExact
  7472. else if ParamResolved.BaseType=btContext then
  7473. begin
  7474. if IsDynArray(ParamResolved.TypeEl) then
  7475. Result:=cExact;
  7476. end;
  7477. end;
  7478. if Result=cIncompatible then
  7479. exit(CheckRaiseTypeArgNo(20170216152250,1,Param,ParamResolved,
  7480. 'string or dynamic array variable',RaiseOnError));
  7481. // second param: new length
  7482. Param:=Params.Params[1];
  7483. ComputeElement(Param,ParamResolved,[]);
  7484. Result:=cIncompatible;
  7485. if (rrfReadable in ParamResolved.Flags)
  7486. and (ParamResolved.BaseType in btAllInteger) then
  7487. Result:=cExact;
  7488. if Result=cIncompatible then
  7489. exit(CheckRaiseTypeArgNo(20170329160338,2,Param,ParamResolved,
  7490. 'integer',RaiseOnError));
  7491. Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError);
  7492. end;
  7493. procedure TPasResolver.BI_SetLength_OnFinishParamsExpr(
  7494. Proc: TResElDataBuiltInProc; Params: TParamsExpr);
  7495. var
  7496. P: TPasExprArray;
  7497. begin
  7498. if Proc=nil then ;
  7499. P:=Params.Params;
  7500. AccessExpr(P[0],rraVarParam);
  7501. AccessExpr(P[1],rraRead);
  7502. end;
  7503. function TPasResolver.BI_InExclude_OnGetCallCompatibility(
  7504. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7505. // check params of built in proc 'include'
  7506. var
  7507. Params: TParamsExpr;
  7508. Param: TPasExpr;
  7509. ParamResolved: TPasResolverResult;
  7510. EnumType: TPasEnumType;
  7511. begin
  7512. if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
  7513. exit(cIncompatible);
  7514. Params:=TParamsExpr(Expr);
  7515. // first param: variable of set of enumtype
  7516. Param:=Params.Params[0];
  7517. ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
  7518. EnumType:=nil;
  7519. if ([rrfReadable,rrfWritable]*ParamResolved.Flags=[rrfReadable,rrfWritable])
  7520. and ((ParamResolved.IdentEl is TPasVariable)
  7521. or (ParamResolved.IdentEl is TPasArgument)) then
  7522. begin
  7523. if (ParamResolved.BaseType=btSet)
  7524. and (ParamResolved.TypeEl is TPasEnumType) then
  7525. EnumType:=TPasEnumType(ParamResolved.TypeEl);
  7526. end;
  7527. if EnumType=nil then
  7528. begin
  7529. {$IFDEF VerbosePasResolver}
  7530. writeln('TPasResolver.OnGetCallCompatibility_InExclude ',GetResolverResultDbg(ParamResolved));
  7531. {$ENDIF}
  7532. exit(CheckRaiseTypeArgNo(20170216152301,1,Param,ParamResolved,
  7533. 'variable of set of enumtype',RaiseOnError));
  7534. end;
  7535. // second param: enum
  7536. Param:=Params.Params[1];
  7537. ComputeElement(Param,ParamResolved,[]);
  7538. if (not (rrfReadable in ParamResolved.Flags))
  7539. or (ParamResolved.TypeEl<>EnumType) then
  7540. begin
  7541. if RaiseOnError then
  7542. RaiseIncompatibleType(20170216152302,nIncompatibleTypeArgNo,
  7543. ['2'],ParamResolved.TypeEl,EnumType,Param);
  7544. exit(cIncompatible);
  7545. end;
  7546. Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError);
  7547. end;
  7548. procedure TPasResolver.BI_InExclude_OnFinishParamsExpr(
  7549. Proc: TResElDataBuiltInProc; Params: TParamsExpr);
  7550. var
  7551. P: TPasExprArray;
  7552. begin
  7553. if Proc=nil then ;
  7554. P:=Params.Params;
  7555. AccessExpr(P[0],rraVarParam);
  7556. AccessExpr(P[1],rraRead);
  7557. end;
  7558. function TPasResolver.BI_Break_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  7559. Expr: TPasExpr; RaiseOnError: boolean): integer;
  7560. var
  7561. Params: TParamsExpr;
  7562. begin
  7563. if GetLoop(Expr)=nil then
  7564. RaiseMsg(20170216152306,nMustBeInsideALoop,sMustBeInsideALoop,['Break'],Expr);
  7565. if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)=0) then
  7566. exit(cExact);
  7567. Params:=TParamsExpr(Expr);
  7568. {$IFDEF VerbosePasResolver}
  7569. writeln('TPasResolver.OnGetCallCompatibility_Break Params=',length(Params.Params));
  7570. {$ENDIF}
  7571. Result:=CheckBuiltInMaxParamCount(Proc,Params,0,RaiseOnError);
  7572. end;
  7573. function TPasResolver.BI_Continue_OnGetCallCompatibility(
  7574. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7575. var
  7576. Params: TParamsExpr;
  7577. begin
  7578. if GetLoop(Expr)=nil then
  7579. RaiseMsg(20170216152309,nMustBeInsideALoop,sMustBeInsideALoop,['Continue'],Expr);
  7580. if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)=0) then
  7581. exit(cExact);
  7582. Params:=TParamsExpr(Expr);
  7583. {$IFDEF VerbosePasResolver}
  7584. writeln('TPasResolver.OnGetCallCompatibility_Continue Params=',length(Params.Params));
  7585. {$ENDIF}
  7586. Result:=CheckBuiltInMaxParamCount(Proc,Params,0,RaiseOnError);
  7587. end;
  7588. function TPasResolver.BI_Exit_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  7589. Expr: TPasExpr; RaiseOnError: boolean): integer;
  7590. var
  7591. Params: TParamsExpr;
  7592. Param: TPasExpr;
  7593. ParamResolved, ResultResolved: TPasResolverResult;
  7594. i: Integer;
  7595. ProcScope: TPasProcedureScope;
  7596. ResultEl: TPasResultElement;
  7597. Flags: TPasResolverComputeFlags;
  7598. begin
  7599. if (not (Expr is TParamsExpr)) or (length(TParamsExpr(Expr).Params)=0) then
  7600. exit(cExact);
  7601. Params:=TParamsExpr(Expr);
  7602. {$IFDEF VerbosePasResolver}
  7603. writeln('TPasResolver.OnGetCallCompatibility_Exit Params=',length(Params.Params));
  7604. {$ENDIF}
  7605. // first param: result
  7606. Param:=Params.Params[0];
  7607. Result:=cIncompatible;
  7608. i:=ScopeCount-1;
  7609. while (i>0) and (not (Scopes[i] is TPasProcedureScope)) do dec(i);
  7610. if i>0 then
  7611. begin
  7612. // first param is function result
  7613. ProcScope:=TPasProcedureScope(Scopes[i]);
  7614. if not (ProcScope.Element is TPasFunction) then
  7615. begin
  7616. if RaiseOnError then
  7617. RaiseMsg(20170216152312,nWrongNumberOfParametersForCallTo,
  7618. sWrongNumberOfParametersForCallTo,['procedure exit'],Params.Params[0]);
  7619. exit(cIncompatible);
  7620. end;
  7621. ResultEl:=(ProcScope.Element as TPasFunction).FuncType.ResultEl;
  7622. ComputeElement(ResultEl,ResultResolved,[rcType]);
  7623. end
  7624. else
  7625. begin
  7626. // default: main program, param is an integer
  7627. SetResolverTypeExpr(ResultResolved,btLongint,FBaseTypes[btLongint],[rrfReadable,rrfWritable]);
  7628. end;
  7629. {$IFDEF VerbosePasResolver}
  7630. writeln('TPasResolver.OnGetCallCompatibility_Exit ResultResolved=',GetResolverResultDbg(ResultResolved));
  7631. {$ENDIF}
  7632. Flags:=[];
  7633. if IsProcedureType(ResultResolved,true) then
  7634. Include(Flags,rcNoImplicitProc);
  7635. ComputeElement(Param,ParamResolved,Flags);
  7636. {$IFDEF VerbosePasResolver}
  7637. writeln('TPasResolver.OnGetCallCompatibility_Exit ParamResolved=',GetResolverResultDbg(ParamResolved));
  7638. {$ENDIF}
  7639. if rrfReadable in ParamResolved.Flags then
  7640. Result:=CheckAssignResCompatibility(ResultResolved,ParamResolved,Param,false);
  7641. if Result=cIncompatible then
  7642. begin
  7643. if RaiseOnError then
  7644. RaiseIncompatibleTypeRes(20170216152314,nIncompatibleTypeArgNo,
  7645. ['1'],ParamResolved,ResultResolved,Param);
  7646. exit;
  7647. end;
  7648. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  7649. end;
  7650. function TPasResolver.BI_IncDec_OnGetCallCompatibility(
  7651. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7652. var
  7653. Params: TParamsExpr;
  7654. Param: TPasExpr;
  7655. ParamResolved, IncrResolved: TPasResolverResult;
  7656. begin
  7657. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  7658. exit(cIncompatible);
  7659. Params:=TParamsExpr(Expr);
  7660. // first param: var Integer
  7661. Param:=Params.Params[0];
  7662. ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
  7663. {$IFDEF VerbosePasResolver}
  7664. writeln('TPasResolver.OnGetCallCompatibility_IncDec ParamResolved=',GetResolverResultDbg(ParamResolved));
  7665. {$ENDIF}
  7666. Result:=cIncompatible;
  7667. // Expr must be a variable
  7668. if not ResolvedElCanBeVarParam(ParamResolved) then
  7669. begin
  7670. if RaiseOnError then
  7671. RaiseMsg(20170216152319,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Expr);
  7672. exit;
  7673. end;
  7674. if ParamResolved.BaseType in btAllInteger then
  7675. Result:=cExact;
  7676. if Result=cIncompatible then
  7677. exit(CheckRaiseTypeArgNo(20170216152320,1,Param,ParamResolved,'integer',RaiseOnError));
  7678. if length(Params.Params)=1 then
  7679. exit;
  7680. // second param: increment/decrement
  7681. Param:=Params.Params[1];
  7682. ComputeElement(Param,IncrResolved,[]);
  7683. Result:=cIncompatible;
  7684. if rrfReadable in IncrResolved.Flags then
  7685. begin
  7686. if IncrResolved.BaseType in btAllInteger then
  7687. Result:=cExact;
  7688. end;
  7689. if Result=cIncompatible then
  7690. exit(CheckRaiseTypeArgNo(20170216152322,2,Param,IncrResolved,'integer',RaiseOnError));
  7691. Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError);
  7692. end;
  7693. procedure TPasResolver.BI_IncDec_OnFinishParamsExpr(
  7694. Proc: TResElDataBuiltInProc; Params: TParamsExpr);
  7695. var
  7696. P: TPasExprArray;
  7697. begin
  7698. if Proc=nil then ;
  7699. P:=Params.Params;
  7700. AccessExpr(P[0],rraVarParam);
  7701. if Length(P)>1 then
  7702. AccessExpr(P[1],rraRead);
  7703. end;
  7704. function TPasResolver.BI_Assigned_OnGetCallCompatibility(
  7705. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7706. // check params of built in proc 'Assigned'
  7707. var
  7708. Params: TParamsExpr;
  7709. Param: TPasExpr;
  7710. ParamResolved: TPasResolverResult;
  7711. C: TClass;
  7712. begin
  7713. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  7714. exit(cIncompatible);
  7715. Params:=TParamsExpr(Expr);
  7716. // first param: pointer, class, class instance, proc type or array
  7717. Param:=Params.Params[0];
  7718. ComputeElement(Param,ParamResolved,[rcNoImplicitProcType]);
  7719. Result:=cIncompatible;
  7720. if ParamResolved.BaseType in [btNil,btPointer] then
  7721. Result:=cExact
  7722. else if (ParamResolved.BaseType=btContext) then
  7723. begin
  7724. C:=ParamResolved.TypeEl.ClassType;
  7725. if (C=TPasClassType)
  7726. or (C=TPasClassOfType)
  7727. or C.InheritsFrom(TPasProcedureType)
  7728. or ((C=TPasArrayType) and (length(TPasArrayType(ParamResolved.TypeEl).Ranges)=0)) then
  7729. Result:=cExact;
  7730. end;
  7731. if Result=cIncompatible then
  7732. exit(CheckRaiseTypeArgNo(20170216152329,1,Param,ParamResolved,'class or array',RaiseOnError));
  7733. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  7734. end;
  7735. procedure TPasResolver.BI_Assigned_OnGetCallResult(Proc: TResElDataBuiltInProc;
  7736. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  7737. begin
  7738. SetResolverIdentifier(ResolvedEl,btBoolean,Proc.Proc,FBaseTypes[btBoolean],[rrfReadable]);
  7739. end;
  7740. function TPasResolver.BI_Chr_OnGetCallCompatibility(
  7741. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7742. var
  7743. Params: TParamsExpr;
  7744. Param: TPasExpr;
  7745. ParamResolved: TPasResolverResult;
  7746. begin
  7747. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  7748. exit(cIncompatible);
  7749. Params:=TParamsExpr(Expr);
  7750. // first param: integer
  7751. Param:=Params.Params[0];
  7752. ComputeElement(Param,ParamResolved,[]);
  7753. Result:=cIncompatible;
  7754. if rrfReadable in ParamResolved.Flags then
  7755. begin
  7756. if ParamResolved.BaseType in btAllInteger then
  7757. Result:=cExact;
  7758. end;
  7759. if Result=cIncompatible then
  7760. exit(CheckRaiseTypeArgNo(20170325185321,1,Param,ParamResolved,'integer',RaiseOnError));
  7761. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  7762. end;
  7763. procedure TPasResolver.BI_Chr_OnGetCallResult(Proc: TResElDataBuiltInProc;
  7764. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  7765. begin
  7766. SetResolverIdentifier(ResolvedEl,BaseTypeChar,Proc.Proc,
  7767. FBaseTypes[BaseTypeChar],[rrfReadable]);
  7768. end;
  7769. procedure TPasResolver.BI_Chr_OnEval(Proc: TResElDataBuiltInProc;
  7770. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
  7771. var
  7772. Param: TPasExpr;
  7773. Value: TResEvalValue;
  7774. begin
  7775. Evaluated:=nil;
  7776. Param:=Params.Params[0];
  7777. Value:=Eval(Param,Flags);
  7778. {$IFDEF VerbosePasResEval}
  7779. if Value=nil then
  7780. writeln('TPasResolver.BI_Chr_OnEval Value=NIL')
  7781. else
  7782. writeln('TPasResolver.BI_Chr_OnEval Value=',Value.AsDebugString);
  7783. {$ENDIF}
  7784. if Value=nil then exit;
  7785. try
  7786. Evaluated:=fExprEvaluator.ChrValue(Value,Params);
  7787. finally
  7788. ReleaseEvalValue(Value);
  7789. end;
  7790. if Proc=nil then ;
  7791. end;
  7792. function TPasResolver.BI_Ord_OnGetCallCompatibility(Proc: TResElDataBuiltInProc;
  7793. Expr: TPasExpr; RaiseOnError: boolean): integer;
  7794. var
  7795. Params: TParamsExpr;
  7796. Param: TPasExpr;
  7797. ParamResolved: TPasResolverResult;
  7798. begin
  7799. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  7800. exit(cIncompatible);
  7801. Params:=TParamsExpr(Expr);
  7802. // first param: bool, enum or char
  7803. Param:=Params.Params[0];
  7804. ComputeElement(Param,ParamResolved,[]);
  7805. Result:=cIncompatible;
  7806. if rrfReadable in ParamResolved.Flags then
  7807. begin
  7808. if ParamResolved.BaseType in (btAllBooleans+btAllChars) then
  7809. Result:=cExact
  7810. else if (ParamResolved.BaseType=btContext) and (ParamResolved.TypeEl is TPasEnumType) then
  7811. Result:=cExact;
  7812. end;
  7813. if Result=cIncompatible then
  7814. exit(CheckRaiseTypeArgNo(20170216152334,1,Param,ParamResolved,'enum or char',RaiseOnError));
  7815. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  7816. end;
  7817. procedure TPasResolver.BI_Ord_OnGetCallResult(Proc: TResElDataBuiltInProc;
  7818. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  7819. begin
  7820. SetResolverIdentifier(ResolvedEl,btLongint,Proc.Proc,FBaseTypes[btLongint],[rrfReadable]);
  7821. end;
  7822. procedure TPasResolver.BI_Ord_OnEval(Proc: TResElDataBuiltInProc;
  7823. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
  7824. var
  7825. Param: TPasExpr;
  7826. Value: TResEvalValue;
  7827. begin
  7828. Evaluated:=nil;
  7829. Param:=Params.Params[0];
  7830. Value:=Eval(Param,Flags);
  7831. {$IFDEF VerbosePasResEval}
  7832. if Value=nil then
  7833. writeln('TPasResolver.BI_Ord_OnEval Value=NIL')
  7834. else
  7835. writeln('TPasResolver.BI_Ord_OnEval Value=',Value.AsDebugString);
  7836. {$ENDIF}
  7837. if Value=nil then exit;
  7838. try
  7839. Evaluated:=fExprEvaluator.OrdValue(Value,Params);
  7840. finally
  7841. ReleaseEvalValue(Value);
  7842. end;
  7843. if Proc=nil then ;
  7844. end;
  7845. function TPasResolver.BI_LowHigh_OnGetCallCompatibility(
  7846. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  7847. // check params of built in proc 'Low' or 'High'
  7848. var
  7849. Params: TParamsExpr;
  7850. Param: TPasExpr;
  7851. ParamResolved: TPasResolverResult;
  7852. C: TClass;
  7853. begin
  7854. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  7855. exit(cIncompatible);
  7856. Params:=TParamsExpr(Expr);
  7857. // first param: enumtype, range, built-in ordinal type (char, longint, ...)
  7858. Param:=Params.Params[0];
  7859. ComputeElement(Param,ParamResolved,[]);
  7860. Result:=cIncompatible;
  7861. if not (rrfReadable in ParamResolved.Flags)
  7862. and (ParamResolved.BaseType in btAllRanges) then
  7863. // built-in range e.g. high(char)
  7864. Result:=cExact
  7865. else if ParamResolved.BaseType=btSet then
  7866. Result:=cExact
  7867. else if (ParamResolved.BaseType=btContext) then
  7868. begin
  7869. C:=ParamResolved.TypeEl.ClassType;
  7870. if (C=TPasArrayType)
  7871. or (C=TPasSetType)
  7872. or (C=TPasEnumType) then
  7873. Result:=cExact;
  7874. end;
  7875. if Result=cIncompatible then
  7876. exit(CheckRaiseTypeArgNo(20170216152338,1,Param,ParamResolved,'ordinal type, array or set',RaiseOnError));
  7877. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  7878. end;
  7879. procedure TPasResolver.BI_LowHigh_OnGetCallResult(Proc: TResElDataBuiltInProc;
  7880. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  7881. var
  7882. ArrayEl: TPasArrayType;
  7883. Param: TPasExpr;
  7884. TypeEl: TPasType;
  7885. begin
  7886. Param:=Params.Params[0];
  7887. ComputeElement(Param,ResolvedEl,[]);
  7888. if ResolvedEl.BaseType=btContext then
  7889. begin
  7890. TypeEl:=ResolvedEl.TypeEl;
  7891. if TypeEl.ClassType=TPasArrayType then
  7892. begin
  7893. // array: result type is type of first dimension
  7894. ArrayEl:=TPasArrayType(TypeEl);
  7895. if length(ArrayEl.Ranges)=0 then
  7896. SetResolverIdentifier(ResolvedEl,BaseTypeLength,Proc.Proc,
  7897. FBaseTypes[BaseTypeLength],[rrfReadable])
  7898. else
  7899. begin
  7900. ComputeElement(ArrayEl.Ranges[0],ResolvedEl,[rcConstant]);
  7901. if ResolvedEl.BaseType=btRange then
  7902. ConvertRangeToFirstValue(ResolvedEl);
  7903. end;
  7904. end
  7905. else if TypeEl.ClassType=TPasSetType then
  7906. begin
  7907. ResolvedEl.TypeEl:=TPasSetType(TypeEl).EnumType;
  7908. end;
  7909. end
  7910. else if ResolvedEl.BaseType=btSet then
  7911. begin
  7912. ResolvedEl.BaseType:=ResolvedEl.SubType;
  7913. ResolvedEl.SubType:=btNone;
  7914. end
  7915. else
  7916. ;// ordinal: result type is argument type
  7917. ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable]+[rrfReadable];
  7918. end;
  7919. procedure TPasResolver.BI_LowHigh_OnEval(Proc: TResElDataBuiltInProc;
  7920. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
  7921. var
  7922. Param: TPasExpr;
  7923. ParamResolved: TPasResolverResult;
  7924. var
  7925. TypeEl: TPasType;
  7926. ArrayEl: TPasArrayType;
  7927. Value: TResEvalValue;
  7928. EnumType: TPasEnumType;
  7929. aSet: TResEvalSet;
  7930. Int: MaxPrecInt;
  7931. bt: TResolverBaseType;
  7932. MinInt, MaxInt: int64;
  7933. i: Integer;
  7934. begin
  7935. Evaluated:=nil;
  7936. Param:=Params.Params[0];
  7937. ComputeElement(Param,ParamResolved,[]);
  7938. TypeEl:=ParamResolved.TypeEl;
  7939. if ParamResolved.BaseType=btContext then
  7940. begin
  7941. if TypeEl.ClassType=TPasArrayType then
  7942. begin
  7943. // array: low/high of first dimension
  7944. ArrayEl:=TPasArrayType(TypeEl);
  7945. if length(ArrayEl.Ranges)=0 then
  7946. begin
  7947. // dyn or open array
  7948. if Proc.BuiltIn=bfLow then
  7949. Evaluated:=TResEvalInt.CreateValue(0)
  7950. else if (ParamResolved.IdentEl is TPasVariable)
  7951. and (TPasVariable(ParamResolved.IdentEl).Expr is TPasExpr) then
  7952. RaiseNotYetImplemented(20170601191003,Params)
  7953. else
  7954. exit;
  7955. end
  7956. else
  7957. begin
  7958. // static array
  7959. Evaluated:=EvalRangeLimit(ArrayEl.Ranges[0],Flags,Proc.BuiltIn=bfLow,Param);
  7960. end;
  7961. end
  7962. else if TypeEl.ClassType=TPasSetType then
  7963. begin
  7964. // set: first/last enum
  7965. TypeEl:=TPasSetType(TypeEl).EnumType;
  7966. if TypeEl.ClassType=TPasEnumType then
  7967. begin
  7968. EnumType:=TPasEnumType(TPasSetType(TypeEl).EnumType);
  7969. if Proc.BuiltIn=bfLow then
  7970. Evaluated:=TResEvalEnum.CreateValue(0,TPasEnumValue(EnumType.Values[0]))
  7971. else
  7972. Evaluated:=TResEvalEnum.CreateValue(EnumType.Values.Count-1,
  7973. TPasEnumValue(EnumType.Values[EnumType.Values.Count-1]));
  7974. end
  7975. else
  7976. begin
  7977. {$IFDEF VerbosePasResolver}
  7978. writeln('TPasResolver.BI_LowHigh_OnEval ',GetResolverResultDbg(ParamResolved),' TypeEl=',TypeEl.ClassName);
  7979. {$ENDIF}
  7980. RaiseNotYetImplemented(20170601203026,Params);
  7981. end;
  7982. end
  7983. else if TypeEl.ClassType=TPasEnumType then
  7984. begin
  7985. EnumType:=TPasEnumType(TypeEl);
  7986. if Proc.BuiltIn=bfLow then
  7987. i:=0
  7988. else
  7989. i:=EnumType.Values.Count-1;
  7990. Evaluated:=TResEvalEnum.CreateValue(i,TPasEnumValue(EnumType.Values[i]))
  7991. end;
  7992. end
  7993. else if ParamResolved.BaseType=btSet then
  7994. begin
  7995. Value:=Eval(Param,Flags);
  7996. if Value=nil then exit;
  7997. case Value.Kind of
  7998. revkSetOfInt:
  7999. begin
  8000. aSet:=TResEvalSet(Value);
  8001. if length(aSet.Ranges)=0 then
  8002. RaiseXExpectedButYFound(20170601201637,'ordinal value',Value.AsString,Param);
  8003. if Proc.BuiltIn=bfLow then
  8004. Int:=aSet.Ranges[0].RangeStart
  8005. else
  8006. Int:=aSet.Ranges[length(aSet.Ranges)-1].RangeEnd;
  8007. case aSet.ElKind of
  8008. revskEnum:
  8009. begin
  8010. EnumType:=aSet.IdentEl as TPasEnumType;
  8011. Evaluated:=TResEvalEnum.CreateValue(Int,TPasEnumValue(EnumType.Values[Int]));
  8012. end;
  8013. revskInt:
  8014. Evaluated:=TResEvalInt.CreateValue(Int);
  8015. revskChar:
  8016. if Int<256 then
  8017. Evaluated:=TResEvalString.CreateValue(chr(Int))
  8018. else
  8019. Evaluated:=TResEvalUTF16.CreateValue(widechar(Int));
  8020. revskBool:
  8021. if Int=0 then
  8022. Evaluated:=TResEvalBool.CreateValue(false)
  8023. else
  8024. Evaluated:=TResEvalBool.CreateValue(true)
  8025. end;
  8026. end;
  8027. else
  8028. RaiseXExpectedButYFound(20170601201237,'ordinal value',Value.AsString,Param);
  8029. end;
  8030. end
  8031. else if (TypeEl is TPasUnresolvedSymbolRef)
  8032. and (TypeEl.CustomData is TResElDataBaseType) then
  8033. begin
  8034. // low,high(base type)
  8035. bt:=TResElDataBaseType(TypeEl.CustomData).BaseType;
  8036. bt:=GetActualBaseType(bt);
  8037. if bt in btAllBooleans then
  8038. Evaluated:=TResEvalBool.CreateValue(Proc.BuiltIn=bfHigh)
  8039. else if bt=btQWord then
  8040. begin
  8041. if Proc.BuiltIn=bfLow then
  8042. Evaluated:=TResEvalInt.CreateValue(0)
  8043. else
  8044. Evaluated:=TResEvalUInt.CreateValue(High(QWord));
  8045. end
  8046. else if (bt in (btAllInteger-[btQWord])) and GetIntegerRange(bt,MinInt,MaxInt) then
  8047. begin
  8048. if Proc.BuiltIn=bfLow then
  8049. Evaluated:=TResEvalInt.CreateValue(MinInt)
  8050. else
  8051. Evaluated:=TResEvalInt.CreateValue(MaxInt);
  8052. end
  8053. else if bt in [btChar,btAnsiChar] then
  8054. begin
  8055. if Proc.BuiltIn=bfLow then
  8056. Evaluated:=TResEvalString.CreateValue(#0)
  8057. else
  8058. Evaluated:=TResEvalString.CreateValue(#255);
  8059. end
  8060. else if bt=btWideChar then
  8061. begin
  8062. if Proc.BuiltIn=bfLow then
  8063. Evaluated:=TResEvalUTF16.CreateValue(#0)
  8064. else
  8065. Evaluated:=TResEvalUTF16.CreateValue(#$ffff);
  8066. end
  8067. else
  8068. begin
  8069. {$IFDEF VerbosePasResolver}
  8070. writeln('TPasResolver.BI_LowHigh_OnEval ',GetResolverResultDbg(ParamResolved));
  8071. {$ENDIF}
  8072. RaiseNotYetImplemented(20170602070738,Params);
  8073. end;
  8074. end
  8075. else if ParamResolved.TypeEl is TPasRangeType then
  8076. begin
  8077. // e.g. type t = 2..10;
  8078. Evaluated:=EvalRangeLimit(TPasRangeType(TypeEl).RangeExpr,FLags,Proc.BuiltIn=bfLow,Param);
  8079. end
  8080. else
  8081. begin
  8082. {$IFDEF VerbosePasResolver}
  8083. writeln('TPasResolver.BI_LowHigh_OnEval ',GetResolverResultDbg(ParamResolved));
  8084. {$ENDIF}
  8085. RaiseNotYetImplemented(20170601202353,Params);
  8086. end;
  8087. {$IFDEF VerbosePasResEval}
  8088. if Evaluated=nil then
  8089. writeln('TPasResolver.BI_LowHigh_OnEval END ResolvedEl=',GetResolverResultDbg(ParamResolved),' Evaluated NO SET')
  8090. else
  8091. writeln('TPasResolver.BI_LowHigh_OnEval END ResolvedEl=',GetResolverResultDbg(ParamResolved),' Evaluated=',Evaluated.AsDebugString);
  8092. {$ENDIF}
  8093. end;
  8094. function TPasResolver.BI_PredSucc_OnGetCallCompatibility(
  8095. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8096. // check params of built in proc 'Pred' or 'Succ'
  8097. var
  8098. Params: TParamsExpr;
  8099. Param: TPasExpr;
  8100. ParamResolved: TPasResolverResult;
  8101. begin
  8102. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  8103. exit(cIncompatible);
  8104. Params:=TParamsExpr(Expr);
  8105. // first param: enum, range, set, char or integer
  8106. Param:=Params.Params[0];
  8107. ComputeElement(Param,ParamResolved,[]);
  8108. Result:=cIncompatible;
  8109. if CheckIsOrdinal(ParamResolved,Param,false) then
  8110. Result:=cExact;
  8111. if Result=cIncompatible then
  8112. exit(CheckRaiseTypeArgNo(20170216152343,1,Param,ParamResolved,'ordinal',RaiseOnError));
  8113. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  8114. end;
  8115. procedure TPasResolver.BI_PredSucc_OnGetCallResult(Proc: TResElDataBuiltInProc;
  8116. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  8117. begin
  8118. ComputeElement(Params.Params[0],ResolvedEl,[]);
  8119. ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable];
  8120. end;
  8121. procedure TPasResolver.BI_PredSucc_OnEval(Proc: TResElDataBuiltInProc;
  8122. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
  8123. var
  8124. Param: TPasExpr;
  8125. begin
  8126. //writeln('TPasResolver.BI_PredSucc_OnEval START');
  8127. Evaluated:=nil;
  8128. Param:=Params.Params[0];
  8129. Evaluated:=Eval(Param,Flags);
  8130. //writeln('TPasResolver.BI_PredSucc_OnEval Param=',Evaluated<>nil);
  8131. if Evaluated=nil then exit;
  8132. //writeln('TPasResolver.BI_PredSucc_OnEval Param=',Evaluated.AsString);
  8133. if Evaluated.Element<>nil then
  8134. Evaluated:=Evaluated.Clone;
  8135. if Proc.BuiltIn=bfPred then
  8136. fExprEvaluator.PredValue(Evaluated,Params)
  8137. else
  8138. fExprEvaluator.SuccValue(Evaluated,Params);
  8139. end;
  8140. function TPasResolver.BI_Str_CheckParam(IsFunc: boolean; Param: TPasExpr;
  8141. const ParamResolved: TPasResolverResult; ArgNo: integer; RaiseOnError: boolean
  8142. ): integer;
  8143. function CheckFormat(FormatExpr: TPasExpr; Index: integer;
  8144. const ParamResolved: TPasResolverResult): boolean;
  8145. var
  8146. ResolvedEl: TPasResolverResult;
  8147. Ok: Boolean;
  8148. begin
  8149. if FormatExpr=nil then exit(true);
  8150. Result:=false;
  8151. Ok:=false;
  8152. if ParamResolved.BaseType in btAllFloats then
  8153. // floats supports value:Width:Precision
  8154. Ok:=true
  8155. else
  8156. // all other only support value:Width
  8157. Ok:=Index<2;
  8158. if not Ok then
  8159. begin
  8160. if RaiseOnError then
  8161. RaiseMsg(20170319222319,nIllegalExpression,sIllegalExpression,[],FormatExpr);
  8162. exit;
  8163. end;
  8164. ComputeElement(FormatExpr,ResolvedEl,[]);
  8165. if not (ResolvedEl.BaseType in btAllInteger) then
  8166. begin
  8167. if RaiseOnError then
  8168. RaiseMsg(20170319221515,nXExpectedButYFound,sXExpectedButYFound,
  8169. ['integer',GetResolverResultDescription(ResolvedEl,true)],FormatExpr);
  8170. exit;
  8171. end;
  8172. if not (rrfReadable in ResolvedEl.Flags) then
  8173. begin
  8174. if RaiseOnError then
  8175. RaiseMsg(20170319221755,nNotReadable,sNotReadable,[],FormatExpr);
  8176. exit;
  8177. end;
  8178. Result:=true;
  8179. end;
  8180. var
  8181. TypeEl: TPasType;
  8182. begin
  8183. Result:=cIncompatible;
  8184. if ParamResolved.BaseType in (btAllInteger+btAllBooleans+btAllFloats) then
  8185. Result:=cExact
  8186. else if IsFunc and (ParamResolved.BaseType in btAllStringAndChars) then
  8187. Result:=cExact
  8188. else if ParamResolved.BaseType=btContext then
  8189. begin
  8190. TypeEl:=ParamResolved.TypeEl;
  8191. if TypeEl.ClassType=TPasEnumType then
  8192. Result:=cExact
  8193. end;
  8194. if Result=cIncompatible then
  8195. exit(CheckRaiseTypeArgNo(20170319220517,ArgNo,Param,ParamResolved,'boolean, integer, enum value',RaiseOnError));
  8196. if not CheckFormat(Param.format1,1,ParamResolved) then
  8197. exit(cIncompatible);
  8198. if not CheckFormat(Param.format2,2,ParamResolved) then
  8199. exit(cIncompatible);
  8200. end;
  8201. function TPasResolver.BI_StrProc_OnGetCallCompatibility(
  8202. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8203. // check params of built-in procedure 'Str'
  8204. var
  8205. Params: TParamsExpr;
  8206. Param: TPasExpr;
  8207. ParamResolved: TPasResolverResult;
  8208. begin
  8209. if not CheckBuiltInMinParamCount(Proc,Expr,2,RaiseOnError) then
  8210. exit(cIncompatible);
  8211. Params:=TParamsExpr(Expr);
  8212. if ParentNeedsExprResult(Params) then
  8213. begin
  8214. if RaiseOnError then
  8215. RaiseMsg(20170326084331,nIncompatibleTypesGotExpected,
  8216. sIncompatibleTypesGotExpected,['procedure str','function str'],Params);
  8217. exit(cIncompatible);
  8218. end;
  8219. // first param: boolean, integer, enum, class instance
  8220. Param:=Params.Params[0];
  8221. ComputeElement(Param,ParamResolved,[]);
  8222. Result:=BI_Str_CheckParam(false,Param,ParamResolved,1,RaiseOnError);
  8223. if Result=cIncompatible then
  8224. exit;
  8225. // second parameter: string variable
  8226. Param:=Params.Params[1];
  8227. ComputeElement(Param,ParamResolved,[]);
  8228. Result:=cIncompatible;
  8229. if ResolvedElCanBeVarParam(ParamResolved) then
  8230. begin
  8231. if ParamResolved.BaseType in btAllStrings then
  8232. Result:=cExact;
  8233. end;
  8234. if Result=cIncompatible then
  8235. exit(CheckRaiseTypeArgNo(20170319220806,1,Param,ParamResolved,'string variable',RaiseOnError));
  8236. Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError);
  8237. end;
  8238. procedure TPasResolver.BI_StrProc_OnFinishParamsExpr(Proc: TResElDataBuiltInProc;
  8239. Params: TParamsExpr);
  8240. var
  8241. P: TPasExprArray;
  8242. begin
  8243. if Proc=nil then ;
  8244. P:=Params.Params;
  8245. AccessExpr(P[0],rraRead);
  8246. AccessExpr(P[1],rraVarParam);
  8247. end;
  8248. function TPasResolver.BI_StrFunc_OnGetCallCompatibility(
  8249. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8250. var
  8251. Params: TParamsExpr;
  8252. Param: TPasExpr;
  8253. ParamResolved: TPasResolverResult;
  8254. i: Integer;
  8255. begin
  8256. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  8257. exit(cIncompatible);
  8258. Params:=TParamsExpr(Expr);
  8259. if not ParentNeedsExprResult(Params) then
  8260. begin
  8261. // not in an expression -> the 'procedure str' is needed, not the 'function str'
  8262. if RaiseOnError then
  8263. RaiseMsg(20170326084622,nIncompatibleTypesGotExpected,
  8264. sIncompatibleTypesGotExpected,['function str','procedure str'],Params);
  8265. exit(cIncompatible);
  8266. end;
  8267. // param: string, boolean, integer, enum, class instance
  8268. for i:=0 to length(Params.Params)-1 do
  8269. begin
  8270. Param:=Params.Params[i];
  8271. ComputeElement(Param,ParamResolved,[]);
  8272. Result:=BI_Str_CheckParam(true,Param,ParamResolved,i+1,RaiseOnError);
  8273. if Result=cIncompatible then
  8274. exit;
  8275. end;
  8276. Result:=cExact;
  8277. end;
  8278. procedure TPasResolver.BI_StrFunc_OnGetCallResult(Proc: TResElDataBuiltInProc;
  8279. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  8280. begin
  8281. if Params=nil then ;
  8282. SetResolverIdentifier(ResolvedEl,btString,Proc.Proc,FBaseTypes[btString],[rrfReadable]);
  8283. end;
  8284. procedure TPasResolver.BI_StrFunc_OnEval(Proc: TResElDataBuiltInProc;
  8285. Params: TParamsExpr; Flags: TResEvalFlags; out Evaluated: TResEvalValue);
  8286. begin
  8287. Evaluated:=fExprEvaluator.EvalStrFunc(Params,Flags);
  8288. end;
  8289. function TPasResolver.BI_ConcatArray_OnGetCallCompatibility(
  8290. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8291. var
  8292. Params: TParamsExpr;
  8293. Param: TPasExpr;
  8294. ParamResolved, ElTypeResolved, FirstElTypeResolved: TPasResolverResult;
  8295. i: Integer;
  8296. begin
  8297. Result:=cIncompatible;
  8298. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  8299. exit;
  8300. Params:=TParamsExpr(Expr);
  8301. FirstElTypeResolved:=Default(TPasResolverResult);
  8302. for i:=0 to length(Params.Params)-1 do
  8303. begin
  8304. // all params: array
  8305. Param:=Params.Params[i];
  8306. ComputeElement(Param,ParamResolved,[]);
  8307. if not (rrfReadable in ParamResolved.Flags)
  8308. or (ParamResolved.BaseType<>btContext)
  8309. or not IsDynArray(ParamResolved.TypeEl) then
  8310. exit(CheckRaiseTypeArgNo(20170329181206,i+1,Param,ParamResolved,'dynamic array',RaiseOnError));
  8311. ComputeElement(TPasArrayType(ParamResolved.TypeEl).ElType,ElTypeResolved,[rcType]);
  8312. Include(ElTypeResolved.Flags,rrfReadable);
  8313. if i=0 then
  8314. begin
  8315. FirstElTypeResolved:=ElTypeResolved;
  8316. Include(ElTypeResolved.Flags,rrfWritable);
  8317. end
  8318. else if CheckAssignResCompatibility(FirstElTypeResolved,ElTypeResolved,Param,RaiseOnError)=cIncompatible then
  8319. exit(cIncompatible);
  8320. end;
  8321. end;
  8322. procedure TPasResolver.BI_ConcatArray_OnGetCallResult(
  8323. Proc: TResElDataBuiltInProc; Params: TParamsExpr; out
  8324. ResolvedEl: TPasResolverResult);
  8325. begin
  8326. ComputeElement(Params.Params[0],ResolvedEl,[]);
  8327. ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable];
  8328. end;
  8329. function TPasResolver.BI_CopyArray_OnGetCallCompatibility(
  8330. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8331. var
  8332. Params: TParamsExpr;
  8333. Param: TPasExpr;
  8334. ParamResolved: TPasResolverResult;
  8335. begin
  8336. Result:=cIncompatible;
  8337. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  8338. exit;
  8339. Params:=TParamsExpr(Expr);
  8340. // first param: array
  8341. Param:=Params.Params[0];
  8342. ComputeElement(Param,ParamResolved,[]);
  8343. if (rrfReadable in ParamResolved.Flags)
  8344. and (ParamResolved.BaseType=btContext)
  8345. and IsDynArray(ParamResolved.TypeEl) then
  8346. Result:=cExact;
  8347. if Result=cIncompatible then
  8348. exit(CheckRaiseTypeArgNo(20170329153951,1,Param,ParamResolved,'dynamic array',RaiseOnError));
  8349. if length(Params.Params)=1 then
  8350. exit(cExact);
  8351. // check optional Start index
  8352. Param:=Params.Params[1];
  8353. ComputeElement(Param,ParamResolved,[]);
  8354. if not (rrfReadable in ParamResolved.Flags)
  8355. or not (ParamResolved.BaseType in btAllInteger) then
  8356. exit(CheckRaiseTypeArgNo(20170329164210,2,Param,ParamResolved,'integer',RaiseOnError));
  8357. if length(Params.Params)=2 then
  8358. exit(cExact);
  8359. // check optional Count
  8360. Param:=Params.Params[2];
  8361. ComputeElement(Param,ParamResolved,[]);
  8362. if not (rrfReadable in ParamResolved.Flags)
  8363. or not (ParamResolved.BaseType in btAllInteger) then
  8364. exit(CheckRaiseTypeArgNo(20170329164329,3,Param,ParamResolved,'integer',RaiseOnError));
  8365. Result:=CheckBuiltInMaxParamCount(Proc,Params,3,RaiseOnError);
  8366. end;
  8367. procedure TPasResolver.BI_CopyArray_OnGetCallResult(
  8368. Proc: TResElDataBuiltInProc; Params: TParamsExpr; out
  8369. ResolvedEl: TPasResolverResult);
  8370. begin
  8371. ComputeElement(Params.Params[0],ResolvedEl,[]);
  8372. ResolvedEl.Flags:=ResolvedEl.Flags-[rrfWritable];
  8373. end;
  8374. function TPasResolver.BI_InsertArray_OnGetCallCompatibility(
  8375. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8376. // Insert(Item,var Array,Index)
  8377. var
  8378. Params: TParamsExpr;
  8379. Param, ItemParam: TPasExpr;
  8380. ItemResolved, ParamResolved, ElTypeResolved: TPasResolverResult;
  8381. begin
  8382. Result:=cIncompatible;
  8383. if not CheckBuiltInMinParamCount(Proc,Expr,3,RaiseOnError) then
  8384. exit;
  8385. Params:=TParamsExpr(Expr);
  8386. // check Item
  8387. ItemParam:=Params.Params[0];
  8388. ComputeElement(ItemParam,ItemResolved,[]);
  8389. if not (rrfReadable in ItemResolved.Flags) then
  8390. exit(CheckRaiseTypeArgNo(20170329171400,1,ItemParam,ItemResolved,'value',RaiseOnError));
  8391. // check Array
  8392. Param:=Params.Params[1];
  8393. ComputeElement(Param,ParamResolved,[]);
  8394. if not ResolvedElCanBeVarParam(ParamResolved) then
  8395. begin
  8396. if RaiseOnError then
  8397. RaiseMsg(20170329171514,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Param);
  8398. exit;
  8399. end;
  8400. if (ParamResolved.BaseType<>btContext)
  8401. or not IsDynArray(ParamResolved.TypeEl) then
  8402. exit(CheckRaiseTypeArgNo(20170329172024,2,Param,ParamResolved,'dynamic array',RaiseOnError));
  8403. ComputeElement(TPasArrayType(ParamResolved.TypeEl).ElType,ElTypeResolved,[rcType]);
  8404. if CheckAssignResCompatibility(ElTypeResolved,ItemResolved,ItemParam,RaiseOnError)=cIncompatible then
  8405. exit(cIncompatible);
  8406. // check insert Index
  8407. Param:=Params.Params[2];
  8408. ComputeElement(Param,ParamResolved,[]);
  8409. if not (rrfReadable in ParamResolved.Flags)
  8410. or not (ParamResolved.BaseType in btAllInteger) then
  8411. exit(CheckRaiseTypeArgNo(20170329172348,3,Param,ParamResolved,'integer',RaiseOnError));
  8412. Result:=CheckBuiltInMaxParamCount(Proc,Params,3,RaiseOnError);
  8413. end;
  8414. procedure TPasResolver.BI_InsertArray_OnFinishParamsExpr(
  8415. Proc: TResElDataBuiltInProc; Params: TParamsExpr);
  8416. var
  8417. P: TPasExprArray;
  8418. begin
  8419. if Proc=nil then ;
  8420. P:=Params.Params;
  8421. AccessExpr(P[0],rraRead);
  8422. AccessExpr(P[1],rraVarParam);
  8423. AccessExpr(P[2],rraRead);
  8424. end;
  8425. function TPasResolver.BI_DeleteArray_OnGetCallCompatibility(
  8426. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8427. // Delete(var Array; Start, Count: integer)
  8428. var
  8429. Params: TParamsExpr;
  8430. Param: TPasExpr;
  8431. ParamResolved: TPasResolverResult;
  8432. begin
  8433. Result:=cIncompatible;
  8434. if not CheckBuiltInMinParamCount(Proc,Expr,3,RaiseOnError) then
  8435. exit;
  8436. Params:=TParamsExpr(Expr);
  8437. // check Array
  8438. Param:=Params.Params[0];
  8439. ComputeElement(Param,ParamResolved,[]);
  8440. if not ResolvedElCanBeVarParam(ParamResolved) then
  8441. begin
  8442. if RaiseOnError then
  8443. RaiseMsg(20170329173421,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Param);
  8444. exit;
  8445. end;
  8446. if (ParamResolved.BaseType<>btContext)
  8447. or not IsDynArray(ParamResolved.TypeEl) then
  8448. exit(CheckRaiseTypeArgNo(20170329173434,1,Param,ParamResolved,'dynamic array',RaiseOnError));
  8449. // check param Start
  8450. Param:=Params.Params[1];
  8451. ComputeElement(Param,ParamResolved,[]);
  8452. if not (rrfReadable in ParamResolved.Flags)
  8453. or not (ParamResolved.BaseType in btAllInteger) then
  8454. exit(CheckRaiseTypeArgNo(20170329173613,2,Param,ParamResolved,'integer',RaiseOnError));
  8455. // check param Count
  8456. Param:=Params.Params[2];
  8457. ComputeElement(Param,ParamResolved,[]);
  8458. if not (rrfReadable in ParamResolved.Flags)
  8459. or not (ParamResolved.BaseType in btAllInteger) then
  8460. exit(CheckRaiseTypeArgNo(20170329172348,3,Param,ParamResolved,'integer',RaiseOnError));
  8461. Result:=CheckBuiltInMaxParamCount(Proc,Params,3,RaiseOnError);
  8462. end;
  8463. procedure TPasResolver.BI_DeleteArray_OnFinishParamsExpr(
  8464. Proc: TResElDataBuiltInProc; Params: TParamsExpr);
  8465. var
  8466. P: TPasExprArray;
  8467. begin
  8468. if Proc=nil then ;
  8469. P:=Params.Params;
  8470. AccessExpr(P[0],rraVarParam);
  8471. AccessExpr(P[1],rraRead);
  8472. AccessExpr(P[2],rraRead);
  8473. end;
  8474. function TPasResolver.BI_TypeInfo_OnGetCallCompatibility(
  8475. Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
  8476. var
  8477. Params: TParamsExpr;
  8478. Param: TPasExpr;
  8479. Decl: TPasElement;
  8480. ParamResolved: TPasResolverResult;
  8481. aType: TPasType;
  8482. begin
  8483. Result:=cIncompatible;
  8484. if not CheckBuiltInMinParamCount(Proc,Expr,1,RaiseOnError) then
  8485. exit;
  8486. Params:=TParamsExpr(Expr);
  8487. // check type or var
  8488. Param:=Params.Params[0];
  8489. ComputeElement(Param,ParamResolved,[rcNoImplicitProc]);
  8490. Decl:=ParamResolved.IdentEl;
  8491. aType:=nil;
  8492. if (Decl<>nil) then
  8493. begin
  8494. if Decl is TPasType then
  8495. aType:=TPasType(Decl)
  8496. else if Decl is TPasVariable then
  8497. aType:=TPasVariable(Decl).VarType
  8498. else if Decl.ClassType=TPasArgument then
  8499. aType:=TPasArgument(Decl).ArgType
  8500. else if Decl.ClassType=TPasResultElement then
  8501. aType:=TPasResultElement(Decl).ResultType
  8502. else if Decl is TPasFunction then
  8503. aType:=TPasFunction(Decl).FuncType.ResultEl.ResultType;
  8504. {$IFDEF VerbosePasResolver}
  8505. if aType=nil then
  8506. writeln('TPasResolver.BI_TypeInfo_OnGetCallCompatibility Decl=',GetObjName(Decl));
  8507. {$ENDIF}
  8508. end;
  8509. if aType=nil then
  8510. begin
  8511. {$IFDEF VerbosePasResolver}
  8512. writeln('TPasResolver.BI_TypeInfo_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
  8513. {$ENDIF}
  8514. RaiseMsg(20170411100259,nTypeIdentifierExpected,sTypeIdentifierExpected,[],Param);
  8515. end;
  8516. aType:=ResolveAliasType(aType);
  8517. if not HasTypeInfo(aType) then
  8518. RaiseMsg(20170413200118,nSymbolCannotBePublished,sSymbolCannotBePublished,[],Param);
  8519. Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
  8520. end;
  8521. procedure TPasResolver.BI_TypeInfo_OnGetCallResult(Proc: TResElDataBuiltInProc;
  8522. Params: TParamsExpr; out ResolvedEl: TPasResolverResult);
  8523. begin
  8524. if Proc=nil then;
  8525. if Params=nil then ;
  8526. SetResolverTypeExpr(ResolvedEl,btPointer,FBaseTypes[btPointer],[rrfReadable]);
  8527. end;
  8528. constructor TPasResolver.Create;
  8529. begin
  8530. inherited Create;
  8531. FDefaultScope:=TPasDefaultScope.Create;
  8532. FPendingForwards:=TFPList.Create;
  8533. FBaseTypeChar:=btAnsiChar;
  8534. FBaseTypeString:=btAnsiString;
  8535. FBaseTypeExtended:=btDouble;
  8536. FBaseTypeLength:=btInt64;
  8537. FDynArrayMinIndex:=0;
  8538. FDynArrayMaxIndex:=High(int64);
  8539. FScopeClass_Class:=TPasClassScope;
  8540. FScopeClass_WithExpr:=TPasWithExprScope;
  8541. fExprEvaluator:=TResExprEvaluator.Create;
  8542. fExprEvaluator.OnLog:=@OnExprEvalLog;
  8543. fExprEvaluator.OnEvalIdentifier:=@OnExprEvalIdentifier;
  8544. fExprEvaluator.OnEvalParams:=@OnExprEvalParams;
  8545. PushScope(FDefaultScope);
  8546. end;
  8547. function TPasResolver.CreateElement(AClass: TPTreeElement; const AName: String;
  8548. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  8549. const ASourceFilename: String; ASourceLinenumber: Integer): TPasElement;
  8550. var
  8551. aScanner: TPascalScanner;
  8552. SrcPos: TPasSourcePos;
  8553. begin
  8554. // get source position for good error messages
  8555. aScanner:=CurrentParser.Scanner;
  8556. if (ASourceFilename='') or StoreSrcColumns then
  8557. begin
  8558. SrcPos.FileName:=aScanner.CurFilename;
  8559. SrcPos.Row:=aScanner.CurRow;
  8560. SrcPos.Column:=aScanner.CurColumn;
  8561. end
  8562. else
  8563. begin
  8564. SrcPos.FileName:=ASourceFilename;
  8565. SrcPos.Row:=ASourceLinenumber;
  8566. SrcPos.Column:=0;
  8567. end;
  8568. Result:=CreateElement(AClass,AName,AParent,AVisibility,SrcPos);
  8569. end;
  8570. function TPasResolver.CreateElement(AClass: TPTreeElement; const AName: String;
  8571. AParent: TPasElement; AVisibility: TPasMemberVisibility;
  8572. const ASrcPos: TPasSourcePos): TPasElement;
  8573. var
  8574. El: TPasElement;
  8575. SrcY: integer;
  8576. begin
  8577. {$IFDEF VerbosePasResolver}
  8578. writeln('TPasResolver.CreateElement ',AClass.ClassName,' Name=',AName,' Parent=',GetObjName(AParent),' (',ASrcPos.Row,',',ASrcPos.Column,')');
  8579. {$ENDIF}
  8580. if (AParent=nil) and (FRootElement<>nil) then
  8581. RaiseInternalError(20160922163535,'more than one root element Class="'+AClass.ClassName+'" Root='+GetObjName(FRootElement));
  8582. if ASrcPos.FileName='' then
  8583. RaiseInternalError(20160922163541,'missing filename');
  8584. SrcY:=ASrcPos.Row;
  8585. if StoreSrcColumns then
  8586. begin
  8587. if (ASrcPos.Column<ParserMaxEmbeddedColumn)
  8588. and (SrcY<ParserMaxEmbeddedRow) then
  8589. SrcY:=-(SrcY*ParserMaxEmbeddedColumn+integer(ASrcPos.Column));
  8590. end;
  8591. // create element
  8592. El:=AClass.Create(AName,AParent);
  8593. FLastElement:=El;
  8594. Result:=FLastElement;
  8595. El.Visibility:=AVisibility;
  8596. El.SourceFilename:=ASrcPos.FileName;
  8597. El.SourceLinenumber:=SrcY;
  8598. if FRootElement=nil then
  8599. FRootElement:=Result as TPasModule;
  8600. // create scope
  8601. if (AClass=TPasVariable)
  8602. or (AClass=TPasConst) then
  8603. AddVariable(TPasVariable(El))
  8604. else if (AClass=TPasProperty) then
  8605. AddProperty(TPasProperty(El))
  8606. else if AClass=TPasArgument then
  8607. AddArgument(TPasArgument(El))
  8608. else if AClass=TPasEnumType then
  8609. AddEnumType(TPasEnumType(El))
  8610. else if AClass=TPasEnumValue then
  8611. AddEnumValue(TPasEnumValue(El))
  8612. else if (AClass=TUnresolvedPendingRef) then
  8613. else if (AClass=TPasAliasType)
  8614. or (AClass=TPasTypeAliasType)
  8615. or (AClass=TPasClassOfType)
  8616. or (AClass=TPasArrayType)
  8617. or (AClass=TPasProcedureType)
  8618. or (AClass=TPasFunctionType)
  8619. or (AClass=TPasSetType)
  8620. or (AClass=TPasRangeType) then
  8621. AddType(TPasType(El))
  8622. else if AClass=TPasStringType then
  8623. begin
  8624. AddType(TPasType(El));
  8625. if BaseTypes[btShortString]=nil then
  8626. RaiseMsg(20170419203043,nIllegalQualifier,sIllegalQualifier,['['],El);
  8627. end
  8628. else if AClass=TPasRecordType then
  8629. AddRecordType(TPasRecordType(El))
  8630. else if AClass=TPasClassType then
  8631. AddClassType(TPasClassType(El))
  8632. else if AClass=TPasVariant then
  8633. else if AClass.InheritsFrom(TPasProcedure) then
  8634. AddProcedure(TPasProcedure(El))
  8635. else if AClass=TPasResultElement then
  8636. AddFunctionResult(TPasResultElement(El))
  8637. else if AClass=TProcedureBody then
  8638. AddProcedureBody(TProcedureBody(El))
  8639. else if AClass=TPasImplExceptOn then
  8640. AddExceptOn(TPasImplExceptOn(El))
  8641. else if AClass=TPasImplLabelMark then
  8642. else if AClass=TPasOverloadedProc then
  8643. else if (AClass=TInterfaceSection)
  8644. or (AClass=TImplementationSection)
  8645. or (AClass=TProgramSection)
  8646. or (AClass=TLibrarySection) then
  8647. AddSection(TPasSection(El))
  8648. else if (AClass=TPasModule)
  8649. or (AClass=TPasProgram)
  8650. or (AClass=TPasLibrary) then
  8651. AddModule(TPasModule(El))
  8652. else if AClass=TPasUsesUnit then
  8653. else if AClass.InheritsFrom(TPasExpr) then
  8654. // resolved when finished
  8655. else if AClass.InheritsFrom(TPasImplBlock) then
  8656. // resolved finished
  8657. else
  8658. RaiseNotYetImplemented(20160922163544,El);
  8659. end;
  8660. function TPasResolver.FindElement(const aName: String): TPasElement;
  8661. // called by TPasParser for direct types, e.g. type t = ns1.unit1.tobj.tsub
  8662. var
  8663. p: SizeInt;
  8664. RightPath, CurName: String;
  8665. NeedPop: Boolean;
  8666. CurScopeEl, NextEl, ErrorEl, BestEl: TPasElement;
  8667. CurSection: TPasSection;
  8668. i: Integer;
  8669. UsesUnit: TPasUsesUnit;
  8670. begin
  8671. //writeln('TPasResolver.FindElement Name="',aName,'"');
  8672. ErrorEl:=nil; // use nil to use scanner position as error position
  8673. RightPath:=aName;
  8674. p:=1;
  8675. CurScopeEl:=nil;
  8676. repeat
  8677. p:=Pos('.',RightPath);
  8678. if p<1 then
  8679. begin
  8680. CurName:=RightPath;
  8681. RightPath:='';
  8682. end
  8683. else
  8684. begin
  8685. CurName:=LeftStr(RightPath,p-1);
  8686. Delete(RightPath,1,p);
  8687. if RightPath='' then
  8688. RaiseMsg(20170328003146,nIllegalExpression,sIllegalExpression,[],ErrorEl);
  8689. end;
  8690. {$IFDEF VerbosePasResolver}
  8691. if RightPath<>'' then
  8692. writeln('TPasResolver.FindElement searching scope "',CurName,'" RightPath="',RightPath,'" ...');
  8693. {$ENDIF}
  8694. if not IsValidIdent(CurName) then
  8695. RaiseNotYetImplemented(20170328000033,ErrorEl);
  8696. if CurScopeEl<>nil then
  8697. begin
  8698. NeedPop:=true;
  8699. if CurScopeEl.ClassType=TPasClassType then
  8700. // check visibility
  8701. PushClassDotScope(TPasClassType(CurScopeEl))
  8702. else if CurScopeEl is TPasModule then
  8703. PushModuleDotScope(TPasModule(CurScopeEl))
  8704. else
  8705. RaiseInternalError(20170504174021);
  8706. end
  8707. else
  8708. NeedPop:=false;
  8709. NextEl:=FindElementWithoutParams(CurName,ErrorEl,true);
  8710. if NextEl is TPasModule then
  8711. begin
  8712. if CurScopeEl is TPasModule then
  8713. RaiseXExpectedButYFound(20170328001619,'class',NextEl.ElementTypeName+' '+NextEl.Name,ErrorEl);
  8714. if Pos('.',NextEl.Name)>0 then
  8715. begin
  8716. // dotted module name -> check if the full module name is in aName
  8717. if CompareText(NextEl.Name+'.',LeftStr(aName,length(NextEl.Name)+1))<>0 then
  8718. begin
  8719. if CompareText(NextEl.Name,aName)=0 then
  8720. RaiseXExpectedButYFound(20170504165825,'type',NextEl.ElementTypeName,ErrorEl)
  8721. else
  8722. RaiseIdentifierNotFound(20170504165412,aName,ErrorEl);
  8723. end;
  8724. RightPath:=copy(aName,length(NextEl.Name)+2,length(aName));
  8725. end;
  8726. CurScopeEl:=NextEl;
  8727. end
  8728. else if NextEl.ClassType=TPasUsesUnit then
  8729. begin
  8730. // the first name of a used unit matches -> find longest match
  8731. CurSection:=NextEl.Parent as TPasSection;
  8732. i:=length(CurSection.UsesClause)-1;
  8733. BestEl:=nil;
  8734. while i>=0 do
  8735. begin
  8736. UsesUnit:=CurSection.UsesClause[i];
  8737. CurName:=UsesUnit.Name;
  8738. if IsDottedIdentifierPrefix(CurName,aName)
  8739. and ((BestEl=nil) or (length(CurName)>length(BestEl.Name))) then
  8740. BestEl:=UsesUnit;
  8741. dec(i);
  8742. if (i<0) and (CurSection.ClassType=TImplementationSection) then
  8743. begin
  8744. CurSection:=(CurSection.Parent as TPasModule).InterfaceSection;
  8745. if CurSection=nil then break;
  8746. i:=length(CurSection.UsesClause)-1;
  8747. end;
  8748. end;
  8749. // check module name too
  8750. CurName:=RootElement.Name;
  8751. if IsDottedIdentifierPrefix(CurName,aName)
  8752. and ((BestEl=nil) or (length(CurName)>length(BestEl.Name))) then
  8753. BestEl:=RootElement;
  8754. if BestEl=nil then
  8755. RaiseIdentifierNotFound(20170504172440,aName,ErrorEl);
  8756. RightPath:=copy(aName,length(BestEl.Name)+2,length(aName));
  8757. if BestEl.ClassType=TPasUsesUnit then
  8758. CurScopeEl:=TPasUsesUnit(BestEl).Module
  8759. else
  8760. CurScopeEl:=BestEl;
  8761. end
  8762. else if RightPath<>'' then
  8763. begin
  8764. if (CurScopeEl is TPasClassType) then
  8765. CurScopeEl:=NextEl
  8766. else
  8767. RaiseIdentifierNotFound(20170328001941,CurName,ErrorEl);
  8768. end;
  8769. // restore scope
  8770. if NeedPop then
  8771. PopScope;
  8772. if RightPath='' then
  8773. exit(NextEl);
  8774. until false;
  8775. end;
  8776. function TPasResolver.FindElementWithoutParams(const AName: String;
  8777. ErrorPosEl: TPasElement; NoProcsWithArgs: boolean): TPasElement;
  8778. var
  8779. Data: TPRFindData;
  8780. begin
  8781. Result:=FindElementWithoutParams(AName,Data,ErrorPosEl,NoProcsWithArgs);
  8782. if Data.Found=nil then exit; // forward type: class-of or ^
  8783. CheckFoundElement(Data,nil);
  8784. if (Data.StartScope<>nil) and (Data.StartScope.ClassType=ScopeClass_WithExpr)
  8785. and (wesfNeedTmpVar in TPasWithExprScope(Data.StartScope).Flags) then
  8786. RaiseInternalError(20160923111727); // caller forgot to handle "With", use the other FindElementWithoutParams instead
  8787. end;
  8788. function TPasResolver.FindElementWithoutParams(const AName: String; out
  8789. Data: TPRFindData; ErrorPosEl: TPasElement; NoProcsWithArgs: boolean
  8790. ): TPasElement;
  8791. var
  8792. Abort: boolean;
  8793. begin
  8794. //writeln('TPasResolver.FindIdentifier Name="',AName,'"');
  8795. Result:=Nil;
  8796. Abort:=false;
  8797. Data:=Default(TPRFindData);
  8798. Data.ErrorPosEl:=ErrorPosEl;
  8799. IterateElements(AName,@OnFindFirstElement,@Data,Abort);
  8800. Result:=Data.Found;
  8801. if Result=nil then
  8802. begin
  8803. if (ErrorPosEl=nil) and (LastElement<>nil)
  8804. and (LastElement.ClassType=TPasClassOfType)
  8805. and (TPasClassOfType(LastElement).DestType=nil) then
  8806. begin
  8807. // 'class of' of a not yet defined class
  8808. Result:=CreateElement(TUnresolvedPendingRef,AName,LastElement,visDefault,
  8809. CurrentParser.CurSourcePos);
  8810. exit;
  8811. end;
  8812. RaiseIdentifierNotFound(20170216152722,AName,ErrorPosEl);
  8813. end;
  8814. if NoProcsWithArgs and (Result is TPasProcedure)
  8815. and ProcNeedsParams(TPasProcedure(Result).ProcType)
  8816. then
  8817. // proc needs parameters
  8818. RaiseMsg(20170216152347,nWrongNumberOfParametersForCallTo,
  8819. sWrongNumberOfParametersForCallTo,[GetProcTypeDescription(TPasProcedure(Result).ProcType)],ErrorPosEl);
  8820. end;
  8821. procedure TPasResolver.FindLongestUnitName(var El: TPasElement; Expr: TPasExpr);
  8822. // Input: El is TPasUsesUnit
  8823. // Output: El is either a TPasUsesUnit or the root module
  8824. var
  8825. CurUsesUnit: TPasUsesUnit;
  8826. BestEl: TPasElement;
  8827. aName, CurName: String;
  8828. Clause: TPasUsesClause;
  8829. i: Integer;
  8830. Section: TPasSection;
  8831. begin
  8832. {$IFDEF VerbosePasResolver}
  8833. //writeln('TPasResolver.FindLongestUnitName El=',GetObjName(El),' Expr=',GetObjName(Expr));
  8834. {$ENDIF}
  8835. if not (El is TPasUsesUnit) then
  8836. RaiseInternalError(20170503000945);
  8837. aName:=GetNameExprValue(Expr);
  8838. if aName='' then
  8839. RaiseNotYetImplemented(20170503110217,Expr);
  8840. repeat
  8841. Expr:=GetNextDottedExpr(Expr);
  8842. if Expr=nil then break;
  8843. CurName:=GetNameExprValue(Expr);
  8844. if CurName='' then
  8845. RaiseNotYetImplemented(20170502164242,Expr);
  8846. aName:=aName+'.'+CurName;
  8847. until false;
  8848. {$IFDEF VerbosePasResolver}
  8849. //writeln('TPasResolver.FindLongestUnitName Dotted="',aName,'"');
  8850. {$ENDIF}
  8851. // search in uses clause
  8852. BestEl:=nil;
  8853. Section:=TPasUsesUnit(El).Parent as TPasSection;
  8854. repeat
  8855. Clause:=Section.UsesClause;
  8856. for i:=0 to length(Clause)-1 do
  8857. begin
  8858. CurUsesUnit:=Clause[i];
  8859. CurName:=CurUsesUnit.Name;
  8860. if IsDottedIdentifierPrefix(CurName,aName)
  8861. and ((BestEl=nil) or (length(CurName)>length(BestEl.Name))) then
  8862. BestEl:=CurUsesUnit; // a better match
  8863. end;
  8864. if Section is TImplementationSection then
  8865. begin
  8866. // search in interface uses clause too
  8867. Section:=(Section.Parent as TPasModule).InterfaceSection;
  8868. end
  8869. else
  8870. break;
  8871. until Section=nil;
  8872. {$IFDEF VerbosePasResolver}
  8873. //writeln('TPasResolver.FindLongestUnitName LongestUnit="',GetObjName(BestEl),'"');
  8874. {$ENDIF}
  8875. // check module name
  8876. CurName:=El.GetModule.Name;
  8877. if IsDottedIdentifierPrefix(CurName,aName)
  8878. and ((BestEl=nil) or (length(CurName)>length(BestEl.Name))) then
  8879. BestEl:=El.GetModule; // a better match
  8880. if BestEl=nil then
  8881. begin
  8882. // no dotted module name fits the expression
  8883. RaiseIdentifierNotFound(20170503140643,GetNameExprValue(Expr),Expr);
  8884. end;
  8885. El:=BestEl;
  8886. {$IFDEF VerbosePasResolver}
  8887. //writeln('TPasResolver.FindLongestUnitName END Best="',GetObjName(El),'"');
  8888. {$ENDIF}
  8889. end;
  8890. procedure TPasResolver.IterateElements(const aName: string;
  8891. const OnIterateElement: TIterateScopeElement; Data: Pointer;
  8892. var Abort: boolean);
  8893. var
  8894. i: Integer;
  8895. Scope: TPasScope;
  8896. begin
  8897. for i:=FScopeCount-1 downto 0 do
  8898. begin
  8899. Scope:=Scopes[i];
  8900. Scope.IterateElements(AName,Scope,OnIterateElement,Data,Abort);
  8901. if Abort then
  8902. exit;
  8903. if Scope is TPasSubScope then break;
  8904. end;
  8905. end;
  8906. procedure TPasResolver.CheckFoundElement(
  8907. const FindData: TPRFindData; Ref: TResolvedReference);
  8908. // check visibility rules
  8909. // Call this method after finding an element by searching the scopes.
  8910. var
  8911. Proc: TPasProcedure;
  8912. Context: TPasElement;
  8913. FoundContext: TPasClassType;
  8914. StartScope: TPasScope;
  8915. OnlyTypeMembers: Boolean;
  8916. TypeEl: TPasType;
  8917. C: TClass;
  8918. begin
  8919. StartScope:=FindData.StartScope;
  8920. OnlyTypeMembers:=false;
  8921. if StartScope is TPasDotIdentifierScope then
  8922. begin
  8923. OnlyTypeMembers:=TPasDotIdentifierScope(StartScope).OnlyTypeMembers;
  8924. Include(Ref.Flags,rrfDotScope);
  8925. if TPasDotIdentifierScope(StartScope).ConstParent then
  8926. Include(Ref.Flags,rrfConstInherited);
  8927. end
  8928. else if StartScope.ClassType=ScopeClass_WithExpr then
  8929. begin
  8930. OnlyTypeMembers:=wesfOnlyTypeMembers in TPasWithExprScope(StartScope).Flags;
  8931. Include(Ref.Flags,rrfDotScope);
  8932. if wesfConstParent in TPasWithExprScope(StartScope).Flags then
  8933. Include(Ref.Flags,rrfConstInherited);
  8934. end
  8935. else if StartScope.ClassType=TPasProcedureScope then
  8936. begin
  8937. Proc:=TPasProcedureScope(StartScope).Element as TPasProcedure;
  8938. //writeln('TPasResolver.CheckFoundElement ',GetObjName(Proc),' ',IsClassMethod(Proc),' ElScope=',GetObjName(FindData.ElScope));
  8939. if (FindData.ElScope<>StartScope) and IsClassMethod(Proc) then
  8940. OnlyTypeMembers:=true;
  8941. end;
  8942. //writeln('TPasResolver.CheckFoundElOnStartScope StartScope=',StartScope.ClassName,
  8943. // ' StartIsDot=',StartScope is TPasDotIdentifierScope,
  8944. // ' OnlyTypeMembers=',(StartScope is TPasDotIdentifierScope)
  8945. // and TPasDotIdentifierScope(StartScope).OnlyTypeMembers,
  8946. // ' FindData.Found=',GetObjName(FindData.Found));
  8947. if OnlyTypeMembers then
  8948. begin
  8949. //writeln('TPasResolver.CheckFoundElOnStartScope ',GetObjName(FindData.Found),' ',(FindData.Found is TPasVariable)
  8950. // and (vmClass in TPasVariable(FindData.Found).VarModifiers));
  8951. // only class vars/procs allowed
  8952. if (FindData.Found.ClassType=TPasConstructor) then
  8953. // constructor: ok
  8954. else if IsClassMethod(FindData.Found)
  8955. then
  8956. // class proc: ok
  8957. else if (FindData.Found is TPasVariable)
  8958. and (vmClass in TPasVariable(FindData.Found).VarModifiers) then
  8959. // class var/const/property: ok
  8960. else
  8961. begin
  8962. RaiseMsg(20170216152348,nCannotAccessThisMemberFromAX,
  8963. sCannotAccessThisMemberFromAX,[FindData.Found.Parent.ElementTypeName],FindData.ErrorPosEl);
  8964. end;
  8965. end
  8966. else if (proExtClassInstanceNoTypeMembers in Options)
  8967. and (StartScope.ClassType=TPasDotClassScope)
  8968. and TPasClassType(TPasDotClassScope(StartScope).ClassScope.Element).IsExternal then
  8969. begin
  8970. // found member in external class instance
  8971. C:=FindData.Found.ClassType;
  8972. if (C=TPasProcedure) or (C=TPasFunction) then
  8973. // ok
  8974. else if C.InheritsFrom(TPasVariable)
  8975. and (not (vmClass in TPasVariable(FindData.Found).VarModifiers)) then
  8976. // ok
  8977. else
  8978. begin
  8979. RaiseMsg(20170331184224,nExternalClassInstanceCannotAccessStaticX,
  8980. sExternalClassInstanceCannotAccessStaticX,
  8981. [FindData.Found.ElementTypeName+' '+FindData.Found.Name],
  8982. FindData.ErrorPosEl);
  8983. end;
  8984. end;
  8985. if (FindData.Found is TPasProcedure) then
  8986. begin
  8987. Proc:=TPasProcedure(FindData.Found);
  8988. if Proc.IsVirtual or Proc.IsOverride then
  8989. begin
  8990. if (StartScope.ClassType=TPasDotClassScope)
  8991. and TPasDotClassScope(StartScope).InheritedExpr then
  8992. begin
  8993. // call directly
  8994. if Proc.IsAbstract then
  8995. RaiseMsg(20170216152352,nAbstractMethodsCannotBeCalledDirectly,
  8996. sAbstractMethodsCannotBeCalledDirectly,[],FindData.ErrorPosEl);
  8997. end
  8998. else
  8999. begin
  9000. // call via virtual method table
  9001. if Ref<>nil then
  9002. Ref.Flags:=Ref.Flags+[rrfVMT];
  9003. end;
  9004. end;
  9005. // constructor: NewInstance or normal call
  9006. // it is a NewInstance iff the scope is a class, e.g. TObject.Create
  9007. if (Proc.ClassType=TPasConstructor)
  9008. and OnlyTypeMembers
  9009. and (Ref<>nil) then
  9010. begin
  9011. Ref.Flags:=Ref.Flags+[rrfNewInstance]-[rrfConstInherited];
  9012. // store the class in Ref.Context
  9013. if Ref.Context<>nil then
  9014. RaiseInternalError(20170131141936);
  9015. Ref.Context:=TResolvedRefCtxConstructor.Create;
  9016. if StartScope is TPasDotClassScope then
  9017. TypeEl:=TPasDotClassScope(StartScope).ClassScope.Element as TPasType
  9018. else if (StartScope is TPasWithExprScope)
  9019. and (TPasWithExprScope(StartScope).Scope is TPasClassScope) then
  9020. TypeEl:=TPasClassScope(TPasWithExprScope(StartScope).Scope).Element as TPasType
  9021. else if (StartScope is TPasProcedureScope) then
  9022. TypeEl:=TPasProcedureScope(StartScope).ClassScope.Element as TPasType
  9023. else
  9024. RaiseInternalError(20170131150855,GetObjName(StartScope));
  9025. TResolvedRefCtxConstructor(Ref.Context).Typ:=TypeEl;
  9026. end;
  9027. {$IFDEF VerbosePasResolver}
  9028. if (Proc.ClassType=TPasConstructor) then
  9029. begin
  9030. write('TPasResolver.CheckFoundElement ',GetObjName(Proc));
  9031. if Ref=nil then
  9032. write(' no ref!')
  9033. else
  9034. begin
  9035. write(' rrfNewInstance=',rrfNewInstance in Ref.Flags,
  9036. ' StartScope=',GetObjName(StartScope),
  9037. ' OnlyTypeMembers=',OnlyTypeMembers);
  9038. end;
  9039. writeln;
  9040. end;
  9041. {$ENDIF}
  9042. // destructor: FreeInstance or normal call
  9043. // it is a normal call if 'inherited'
  9044. if (Proc.ClassType=TPasDestructor) and (Ref<>nil) then
  9045. if ((StartScope.ClassType<>TPasDotClassScope)
  9046. or (not TPasDotClassScope(StartScope).InheritedExpr)) then
  9047. Ref.Flags:=Ref.Flags+[rrfFreeInstance];
  9048. {$IFDEF VerbosePasResolver}
  9049. if (Proc.ClassType=TPasDestructor) then
  9050. begin
  9051. write('TPasResolver.CheckFoundElement ',GetObjName(Proc));
  9052. if Ref=nil then
  9053. write(' no ref!')
  9054. else
  9055. begin
  9056. write(' rrfFreeInstance=',rrfFreeInstance in Ref.Flags,
  9057. ' StartScope=',GetObjName(StartScope));
  9058. if StartScope.ClassType=TPasDotClassScope then
  9059. write(' InheritedExpr=',TPasDotClassScope(StartScope).InheritedExpr);
  9060. end;
  9061. writeln;
  9062. end;
  9063. {$ENDIF}
  9064. end;
  9065. // check class visibility
  9066. if FindData.Found.Visibility in [visPrivate,visProtected,visStrictPrivate,visStrictProtected] then
  9067. begin
  9068. Context:=GetVisibilityContext;
  9069. FoundContext:=FindData.Found.Parent as TPasClassType;
  9070. case FindData.Found.Visibility of
  9071. visPrivate:
  9072. // private members can only be accessed in same module
  9073. if FoundContext.GetModule<>Context.GetModule then
  9074. RaiseMsg(20170216152354,nCantAccessPrivateMember,sCantAccessPrivateMember,
  9075. ['private',FindData.Found.Name],FindData.ErrorPosEl);
  9076. visProtected:
  9077. // protected members can only be accessed in same module or descendant classes
  9078. if FoundContext.GetModule=Context.GetModule then
  9079. // same module -> ok
  9080. else if (Context is TPasType)
  9081. and (CheckClassIsClass(TPasType(Context),FoundContext,FindData.ErrorPosEl)<>cIncompatible) then
  9082. // context in class or descendant
  9083. else
  9084. RaiseMsg(20170216152356,nCantAccessPrivateMember,sCantAccessPrivateMember,
  9085. ['protected',FindData.Found.Name],FindData.ErrorPosEl);
  9086. visStrictPrivate:
  9087. // strict private members can only be accessed in their class
  9088. if Context<>FoundContext then
  9089. RaiseMsg(20170216152357,nCantAccessPrivateMember,sCantAccessPrivateMember,
  9090. ['strict private',FindData.Found.Name],FindData.ErrorPosEl);
  9091. visStrictProtected:
  9092. // strict protected members can only be access in their and descendant classes
  9093. if (Context is TPasType)
  9094. and (CheckClassIsClass(TPasType(Context),FoundContext,FindData.ErrorPosEl)<>cIncompatible) then
  9095. // context in class or descendant
  9096. else
  9097. RaiseMsg(20170216152400,nCantAccessPrivateMember,sCantAccessPrivateMember,
  9098. ['strict protected',FindData.Found.Name],FindData.ErrorPosEl);
  9099. end;
  9100. end;
  9101. end;
  9102. function TPasResolver.GetVisibilityContext: TPasElement;
  9103. var
  9104. i: Integer;
  9105. begin
  9106. for i:=ScopeCount-1 downto 0 do
  9107. begin
  9108. Result:=Scopes[i].VisibilityContext;
  9109. if Result<>nil then exit;
  9110. end;
  9111. Result:=nil;
  9112. end;
  9113. procedure TPasResolver.FinishScope(ScopeType: TPasScopeType; El: TPasElement);
  9114. begin
  9115. case ScopeType of
  9116. stModule: FinishModule(El as TPasModule);
  9117. stUsesClause: FinishUsesClause;
  9118. stTypeSection: FinishTypeSection(El as TPasDeclarations);
  9119. stTypeDef: FinishTypeDef(El as TPasType);
  9120. stConstDef: FinishConstDef(El as TPasConst);
  9121. stProcedure: FinishProcedure(El as TPasProcedure);
  9122. stProcedureHeader: FinishProcedureType(El as TPasProcedureType);
  9123. stExceptOnExpr: FinishExceptOnExpr;
  9124. stExceptOnStatement: FinishExceptOnStatement;
  9125. stDeclaration: FinishDeclaration(El);
  9126. stAncestors: FinishAncestors(El as TPasClassType);
  9127. else
  9128. RaiseMsg(20170216152401,nNotYetImplemented,sNotYetImplemented+' FinishScope',[IntToStr(ord(ScopeType))],nil);
  9129. end;
  9130. end;
  9131. function TPasResolver.NeedArrayValues(El: TPasElement): boolean;
  9132. // called by the parser when reading DoParseConstValueExpression
  9133. var
  9134. C: TClass;
  9135. V: TPasVariable;
  9136. TypeEl: TPasType;
  9137. begin
  9138. Result:=false;
  9139. if El=nil then exit;
  9140. C:=El.ClassType;
  9141. if (C=TPasConst) or (C=TPasVariable) then
  9142. begin
  9143. V:=TPasVariable(El);
  9144. if V.VarType=nil then exit;
  9145. TypeEl:=ResolveAliasType(V.VarType);
  9146. Result:=TypeEl.ClassType=TPasArrayType;
  9147. end;
  9148. //writeln('TPasResolver.NeedArrayValues ',GetObjName(El));
  9149. end;
  9150. class procedure TPasResolver.UnmangleSourceLineNumber(LineNumber: integer; out
  9151. Line, Column: integer);
  9152. begin
  9153. Line:=Linenumber;
  9154. Column:=0;
  9155. if Line<0 then begin
  9156. Line:=-Line;
  9157. Column:=Line mod ParserMaxEmbeddedColumn;
  9158. Line:=Line div ParserMaxEmbeddedColumn;
  9159. end;
  9160. end;
  9161. class function TPasResolver.GetElementSourcePosStr(El: TPasElement): string;
  9162. var
  9163. Line, Column: integer;
  9164. begin
  9165. if El=nil then exit('nil');
  9166. UnmangleSourceLineNumber(El.SourceLinenumber,Line,Column);
  9167. Result:=El.SourceFilename+'('+IntToStr(Line);
  9168. if Column>0 then
  9169. Result:=Result+','+IntToStr(Column);
  9170. Result:=Result+')';
  9171. end;
  9172. destructor TPasResolver.Destroy;
  9173. begin
  9174. {$IFDEF VerbosePasResolverMem}
  9175. writeln('TPasResolver.Destroy START ',ClassName);
  9176. {$ENDIF}
  9177. Clear;
  9178. {$IFDEF VerbosePasResolverMem}
  9179. writeln('TPasResolver.Destroy PopScope...');
  9180. {$ENDIF}
  9181. PopScope; // free default scope
  9182. {$IFDEF VerbosePasResolverMem}
  9183. writeln('TPasResolver.Destroy FPendingForwards...');
  9184. {$ENDIF}
  9185. FreeAndNil(FPendingForwards);
  9186. FreeAndNil(fExprEvaluator);
  9187. inherited Destroy;
  9188. {$IFDEF VerbosePasResolverMem}
  9189. writeln('TPasResolver.Destroy END ',ClassName);
  9190. {$ENDIF}
  9191. end;
  9192. procedure TPasResolver.Clear;
  9193. begin
  9194. RestoreSubScopes(0);
  9195. // clear stack, keep DefaultScope
  9196. while (FScopeCount>0) and (FTopScope<>DefaultScope) do
  9197. PopScope;
  9198. ClearResolveDataList(lkModule);
  9199. end;
  9200. procedure TPasResolver.ClearBuiltInIdentifiers;
  9201. var
  9202. bt: TResolverBaseType;
  9203. begin
  9204. ClearResolveDataList(lkBuiltIn);
  9205. for bt in TResolverBaseType do
  9206. FBaseTypes[bt]:=nil;
  9207. end;
  9208. procedure TPasResolver.AddObjFPCBuiltInIdentifiers(
  9209. const TheBaseTypes: TResolveBaseTypes;
  9210. const TheBaseProcs: TResolverBuiltInProcs);
  9211. var
  9212. bt: TResolverBaseType;
  9213. begin
  9214. for bt in TheBaseTypes do
  9215. AddBaseType(BaseTypeNames[bt],bt);
  9216. if bfLength in TheBaseProcs then
  9217. AddBuiltInProc('Length','function Length(const String or Array): sizeint',
  9218. @BI_Length_OnGetCallCompatibility,@BI_Length_OnGetCallResult,
  9219. @BI_Length_OnEval,nil,bfLength);
  9220. if bfSetLength in TheBaseProcs then
  9221. AddBuiltInProc('SetLength','procedure SetLength(var String or Array; NewLength: sizeint)',
  9222. @BI_SetLength_OnGetCallCompatibility,nil,nil,
  9223. @BI_SetLength_OnFinishParamsExpr,bfSetLength,[bipfCanBeStatement]);
  9224. if bfInclude in TheBaseProcs then
  9225. AddBuiltInProc('Include','procedure Include(var Set of Enum; const Enum)',
  9226. @BI_InExclude_OnGetCallCompatibility,nil,nil,
  9227. @BI_InExclude_OnFinishParamsExpr,bfInclude,[bipfCanBeStatement]);
  9228. if bfExclude in TheBaseProcs then
  9229. AddBuiltInProc('Exclude','procedure Exclude(var Set of Enum; const Enum)',
  9230. @BI_InExclude_OnGetCallCompatibility,nil,nil,
  9231. @BI_InExclude_OnFinishParamsExpr,bfExclude,[bipfCanBeStatement]);
  9232. if bfBreak in TheBaseProcs then
  9233. AddBuiltInProc('Break','procedure Break',
  9234. @BI_Break_OnGetCallCompatibility,nil,nil,nil,bfBreak,[bipfCanBeStatement]);
  9235. if bfContinue in TheBaseProcs then
  9236. AddBuiltInProc('Continue','procedure Continue',
  9237. @BI_Continue_OnGetCallCompatibility,nil,nil,nil,bfContinue,[bipfCanBeStatement]);
  9238. if bfExit in TheBaseProcs then
  9239. AddBuiltInProc('Exit','procedure Exit(result)',
  9240. @BI_Exit_OnGetCallCompatibility,nil,nil,nil,bfExit,[bipfCanBeStatement]);
  9241. if bfInc in TheBaseProcs then
  9242. AddBuiltInProc('Inc','procedure Inc(var Integer; const Incr: Integer = 1)',
  9243. @BI_IncDec_OnGetCallCompatibility,nil,nil,
  9244. @BI_IncDec_OnFinishParamsExpr,bfInc,[bipfCanBeStatement]);
  9245. if bfDec in TheBaseProcs then
  9246. AddBuiltInProc('Dec','procedure Dec(var Integer; const Decr: Integer = 1)',
  9247. @BI_IncDec_OnGetCallCompatibility,nil,nil,
  9248. @BI_IncDec_OnFinishParamsExpr,bfDec,[bipfCanBeStatement]);
  9249. if bfAssigned in TheBaseProcs then
  9250. AddBuiltInProc('Assigned','function Assigned(const Pointer or Class or Class-of): boolean',
  9251. @BI_Assigned_OnGetCallCompatibility,@BI_Assigned_OnGetCallResult,
  9252. nil,nil,bfAssigned);
  9253. if bfChr in TheBaseProcs then
  9254. AddBuiltInProc('Chr','function Chr(const Integer): char',
  9255. @BI_Chr_OnGetCallCompatibility,@BI_Chr_OnGetCallResult,nil,nil,bfChr);
  9256. if bfOrd in TheBaseProcs then
  9257. AddBuiltInProc('Ord','function Ord(const Enum or Char): integer',
  9258. @BI_Ord_OnGetCallCompatibility,@BI_Ord_OnGetCallResult,
  9259. @BI_Ord_OnEval,nil,bfOrd);
  9260. if bfLow in TheBaseProcs then
  9261. AddBuiltInProc('Low','function Low(const array or ordinal): ordinal or integer',
  9262. @BI_LowHigh_OnGetCallCompatibility,@BI_LowHigh_OnGetCallResult,
  9263. @BI_LowHigh_OnEval,nil,bfLow);
  9264. if bfHigh in TheBaseProcs then
  9265. AddBuiltInProc('High','function High(const array or ordinal): ordinal or integer',
  9266. @BI_LowHigh_OnGetCallCompatibility,@BI_LowHigh_OnGetCallResult,
  9267. @BI_LowHigh_OnEval,nil,bfHigh);
  9268. if bfPred in TheBaseProcs then
  9269. AddBuiltInProc('Pred','function Pred(const ordinal): ordinal',
  9270. @BI_PredSucc_OnGetCallCompatibility,@BI_PredSucc_OnGetCallResult,
  9271. @BI_PredSucc_OnEval,nil,bfPred);
  9272. if bfSucc in TheBaseProcs then
  9273. AddBuiltInProc('Succ','function Succ(const ordinal): ordinal',
  9274. @BI_PredSucc_OnGetCallCompatibility,@BI_PredSucc_OnGetCallResult,
  9275. @BI_PredSucc_OnEval,nil,bfSucc);
  9276. if bfStrProc in TheBaseProcs then
  9277. AddBuiltInProc('Str','procedure Str(const var; var String)',
  9278. @BI_StrProc_OnGetCallCompatibility,nil,nil,
  9279. @BI_StrProc_OnFinishParamsExpr,bfStrProc,[bipfCanBeStatement]);
  9280. if bfStrFunc in TheBaseProcs then
  9281. AddBuiltInProc('Str','function Str(const var): String',
  9282. @BI_StrFunc_OnGetCallCompatibility,@BI_StrFunc_OnGetCallResult,
  9283. @BI_StrFunc_OnEval,nil,bfStrFunc);
  9284. if bfConcatArray in TheBaseProcs then
  9285. AddBuiltInProc('Concat','function Concat(const Array1, Array2, ...): Array',
  9286. @BI_ConcatArray_OnGetCallCompatibility,@BI_ConcatArray_OnGetCallResult,
  9287. nil,nil,bfConcatArray);
  9288. if bfCopyArray in TheBaseProcs then
  9289. AddBuiltInProc('Copy','function Copy(const Array; Start: integer = 0; Count: integer = all): Array',
  9290. @BI_CopyArray_OnGetCallCompatibility,@BI_CopyArray_OnGetCallResult,
  9291. nil,nil,bfCopyArray);
  9292. if bfInsertArray in TheBaseProcs then
  9293. AddBuiltInProc('Insert','procedure Insert(const Element; var Array; Index: integer)',
  9294. @BI_InsertArray_OnGetCallCompatibility,nil,nil,
  9295. @BI_InsertArray_OnFinishParamsExpr,bfInsertArray,[bipfCanBeStatement]);
  9296. if bfDeleteArray in TheBaseProcs then
  9297. AddBuiltInProc('Delete','procedure Delete(var Array; Start, Count: integer)',
  9298. @BI_DeleteArray_OnGetCallCompatibility,nil,nil,
  9299. @BI_DeleteArray_OnFinishParamsExpr,bfDeleteArray,[bipfCanBeStatement]);
  9300. if bfTypeInfo in TheBaseProcs then
  9301. AddBuiltInProc('TypeInfo','function TypeInfo(type or var identifier): Pointer',
  9302. @BI_TypeInfo_OnGetCallCompatibility,@BI_TypeInfo_OnGetCallResult,
  9303. nil,nil,bfTypeInfo);
  9304. end;
  9305. function TPasResolver.AddBaseType(const aName: string; Typ: TResolverBaseType
  9306. ): TResElDataBaseType;
  9307. var
  9308. El: TPasUnresolvedSymbolRef;
  9309. begin
  9310. El:=TPasUnresolvedSymbolRef.Create(aName,nil);
  9311. if not (Typ in [btNone,btCustom]) then
  9312. FBaseTypes[Typ]:=El;
  9313. Result:=TResElDataBaseType.Create;
  9314. Result.BaseType:=Typ;
  9315. AddResolveData(El,Result,lkBuiltIn);
  9316. FDefaultScope.AddIdentifier(aName,El,pikBaseType);
  9317. end;
  9318. function TPasResolver.AddCustomBaseType(const aName: string;
  9319. aClass: TResElDataBaseTypeClass): TPasUnresolvedSymbolRef;
  9320. var
  9321. CustomData: TResElDataBaseType;
  9322. begin
  9323. Result:=TPasUnresolvedSymbolRef.Create(aName,nil);
  9324. CustomData:=aClass.Create;
  9325. CustomData.BaseType:=btCustom;
  9326. AddResolveData(Result,CustomData,lkBuiltIn);
  9327. FDefaultScope.AddIdentifier(aName,Result,pikBaseType);
  9328. end;
  9329. function TPasResolver.IsBaseType(aType: TPasType; BaseType: TResolverBaseType;
  9330. ResolveAlias: boolean): boolean;
  9331. begin
  9332. Result:=false;
  9333. if aType=nil then exit;
  9334. if ResolveAlias then
  9335. aType:=ResolveAliasType(aType);
  9336. if aType.ClassType<>TPasUnresolvedSymbolRef then exit;
  9337. Result:=CompareText(aType.Name,BaseTypeNames[BaseType])=0;
  9338. end;
  9339. function TPasResolver.AddBuiltInProc(const aName: string; Signature: string;
  9340. const GetCallCompatibility: TOnGetCallCompatibility;
  9341. const GetCallResult: TOnGetCallResult; const EvalConst: TOnEvalBIFunction;
  9342. const FinishParamsExpr: TOnFinishParamsExpr;
  9343. const BuiltIn: TResolverBuiltInProc; const Flags: TBuiltInProcFlags
  9344. ): TResElDataBuiltInProc;
  9345. var
  9346. El: TPasUnresolvedSymbolRef;
  9347. begin
  9348. El:=TPasUnresolvedSymbolRef.Create(aName,nil);
  9349. Result:=TResElDataBuiltInProc.Create;
  9350. Result.Proc:=El;
  9351. Result.Signature:=Signature;
  9352. Result.BuiltIn:=BuiltIn;
  9353. Result.GetCallCompatibility:=GetCallCompatibility;
  9354. Result.GetCallResult:=GetCallResult;
  9355. Result.Eval:=EvalConst;
  9356. Result.FinishParamsExpression:=FinishParamsExpr;
  9357. Result.Flags:=Flags;
  9358. AddResolveData(El,Result,lkBuiltIn);
  9359. FDefaultScope.AddIdentifier(aName,El,pikBuiltInProc);
  9360. end;
  9361. procedure TPasResolver.AddResolveData(El: TPasElement; Data: TResolveData;
  9362. Kind: TResolveDataListKind);
  9363. begin
  9364. Data.Element:=El;
  9365. Data.Owner:=Self;
  9366. Data.Next:=FLastCreatedData[Kind];
  9367. FLastCreatedData[Kind]:=Data;
  9368. El.CustomData:=Data;
  9369. end;
  9370. function TPasResolver.CreateReference(DeclEl, RefEl: TPasElement;
  9371. Access: TResolvedRefAccess; FindData: PPRFindData): TResolvedReference;
  9372. procedure RaiseAlreadySet;
  9373. var
  9374. FormerDeclEl: TPasElement;
  9375. begin
  9376. writeln('RaiseAlreadySet RefEl=',GetObjName(RefEl),' DeclEl=',GetObjName(DeclEl));
  9377. writeln(' RefEl at ',GetElementSourcePosStr(RefEl));
  9378. writeln(' RefEl.CustomData=',GetObjName(RefEl.CustomData));
  9379. if RefEl.CustomData is TResolvedReference then
  9380. begin
  9381. FormerDeclEl:=TResolvedReference(RefEl.CustomData).Declaration;
  9382. writeln(' TResolvedReference(RefEl.CustomData).Declaration=',GetObjName(FormerDeclEl),
  9383. ' IsSame=',FormerDeclEl=DeclEl);
  9384. end;
  9385. RaiseInternalError(20160922163554,'customdata<>nil');
  9386. end;
  9387. begin
  9388. if RefEl.CustomData<>nil then
  9389. RaiseAlreadySet;
  9390. {$IFDEF VerbosePasResolver}
  9391. writeln('TPasResolver.CreateReference RefEl=',GetObjName(RefEl),' DeclEl=',GetObjName(DeclEl));
  9392. {$ENDIF}
  9393. Result:=TResolvedReference.Create;
  9394. if FindData<>nil then
  9395. begin
  9396. if FindData^.StartScope.ClassType=ScopeClass_WithExpr then
  9397. Result.WithExprScope:=TPasWithExprScope(FindData^.StartScope);
  9398. end;
  9399. AddResolveData(RefEl,Result,lkModule);
  9400. Result.Declaration:=DeclEl;
  9401. if RefEl is TPasExpr then
  9402. SetResolvedRefAccess(TPasExpr(RefEl),Result,Access);
  9403. EmitElementHints(RefEl,DeclEl);
  9404. end;
  9405. function TPasResolver.CreateScope(El: TPasElement; ScopeClass: TPasScopeClass
  9406. ): TPasScope;
  9407. begin
  9408. if not ScopeClass.IsStoredInElement then
  9409. RaiseInternalError(20160923121858);
  9410. if El.CustomData<>nil then
  9411. RaiseInternalError(20160923121849);
  9412. {$IFDEF VerbosePasResolver}
  9413. writeln('TPasResolver.CreateScope El=',GetObjName(El),' ScopeClass=',ScopeClass.ClassName);
  9414. {$ENDIF}
  9415. Result:=ScopeClass.Create;
  9416. if Result.FreeOnPop then
  9417. begin
  9418. Result.Element:=El;
  9419. El.CustomData:=Result;
  9420. Result.Owner:=Self;
  9421. end
  9422. else
  9423. // add to free list
  9424. AddResolveData(El,Result,lkModule);
  9425. end;
  9426. procedure TPasResolver.PopScope;
  9427. var
  9428. Scope: TPasScope;
  9429. begin
  9430. if FScopeCount=0 then
  9431. RaiseInternalError(20160922163557);
  9432. {$IFDEF VerbosePasResolver}
  9433. //writeln('TPasResolver.PopScope ',FScopeCount,' ',FTopScope<>nil,' IsDefault=',FTopScope=FDefaultScope);
  9434. writeln('TPasResolver.PopScope ',FTopScope.ClassName,' IsStoredInElement=',FTopScope.IsStoredInElement,' Element=',GetObjName(FTopScope.Element),' FreeOnPop=',FTopScope.FreeOnPop);
  9435. {$ENDIF}
  9436. dec(FScopeCount);
  9437. if FTopScope.FreeOnPop then
  9438. begin
  9439. Scope:=FScopes[FScopeCount];
  9440. if (Scope.Element<>nil) and (Scope.Element.CustomData=Scope) then
  9441. Scope.Element.CustomData:=nil;
  9442. if Scope=FDefaultScope then
  9443. FDefaultScope:=nil;
  9444. FScopes[FScopeCount]:=nil;
  9445. Scope.Free;
  9446. end;
  9447. if FScopeCount>0 then
  9448. FTopScope:=FScopes[FScopeCount-1]
  9449. else
  9450. FTopScope:=nil;
  9451. end;
  9452. procedure TPasResolver.PushScope(Scope: TPasScope);
  9453. begin
  9454. if Scope=nil then
  9455. RaiseInternalError(20160922163601);
  9456. if length(FScopes)=FScopeCount then
  9457. SetLength(FScopes,FScopeCount*2+10);
  9458. FScopes[FScopeCount]:=Scope;
  9459. inc(FScopeCount);
  9460. FTopScope:=Scope;
  9461. {$IFDEF VerbosePasResolver}
  9462. writeln('TPasResolver.PushScope ScopeCount=',ScopeCount,' ',GetObjName(FTopScope));
  9463. {$ENDIF}
  9464. end;
  9465. function TPasResolver.PushScope(El: TPasElement; ScopeClass: TPasScopeClass
  9466. ): TPasScope;
  9467. begin
  9468. Result:=CreateScope(El,ScopeClass);
  9469. PushScope(Result);
  9470. end;
  9471. function TPasResolver.PushModuleDotScope(aModule: TPasModule): TPasModuleDotScope;
  9472. begin
  9473. Result:=TPasModuleDotScope.Create;
  9474. Result.Owner:=Self;
  9475. Result.Module:=aModule;
  9476. if aModule is TPasProgram then
  9477. begin // program
  9478. if TPasProgram(aModule).ProgramSection<>nil then
  9479. Result.InterfaceScope:=
  9480. TPasProgram(aModule).ProgramSection.CustomData as TPasSectionScope;
  9481. end
  9482. else if aModule is TPasLibrary then
  9483. begin // library
  9484. if TPasLibrary(aModule).LibrarySection<>nil then
  9485. Result.InterfaceScope:=
  9486. TPasLibrary(aModule).LibrarySection.CustomData as TPasSectionScope;
  9487. end
  9488. else
  9489. begin // unit
  9490. if aModule.InterfaceSection<>nil then
  9491. Result.InterfaceScope:=
  9492. aModule.InterfaceSection.CustomData as TPasSectionScope;
  9493. if (aModule=CurrentParser.CurModule)
  9494. and (aModule.ImplementationSection<>nil)
  9495. and (aModule.ImplementationSection.CustomData<>nil)
  9496. then
  9497. Result.ImplementationScope:=aModule.ImplementationSection.CustomData as TPasSectionScope;
  9498. end;
  9499. PushScope(Result);
  9500. end;
  9501. function TPasResolver.PushClassDotScope(var CurClassType: TPasClassType
  9502. ): TPasDotClassScope;
  9503. var
  9504. ClassScope: TPasClassScope;
  9505. Ref: TResolvedReference;
  9506. begin
  9507. if CurClassType.IsForward then
  9508. begin
  9509. Ref:=CurClassType.CustomData as TResolvedReference;
  9510. CurClassType:=Ref.Declaration as TPasClassType;
  9511. end;
  9512. if CurClassType.CustomData=nil then
  9513. RaiseInternalError(20160922163611);
  9514. ClassScope:=CurClassType.CustomData as TPasClassScope;
  9515. Result:=TPasDotClassScope.Create;
  9516. Result.Owner:=Self;
  9517. Result.ClassScope:=ClassScope;
  9518. PushScope(Result);
  9519. end;
  9520. function TPasResolver.PushRecordDotScope(CurRecordType: TPasRecordType
  9521. ): TPasDotRecordScope;
  9522. var
  9523. RecScope: TPasRecordScope;
  9524. begin
  9525. RecScope:=CurRecordType.CustomData as TPasRecordScope;
  9526. Result:=TPasDotRecordScope.Create;
  9527. Result.Owner:=Self;
  9528. Result.IdentifierScope:=RecScope;
  9529. PushScope(Result);
  9530. end;
  9531. function TPasResolver.PushEnumDotScope(CurEnumType: TPasEnumType
  9532. ): TPasDotEnumTypeScope;
  9533. var
  9534. EnumScope: TPasEnumTypeScope;
  9535. begin
  9536. EnumScope:=CurEnumType.CustomData as TPasEnumTypeScope;
  9537. Result:=TPasDotEnumTypeScope.Create;
  9538. Result.Owner:=Self;
  9539. Result.IdentifierScope:=EnumScope;
  9540. PushScope(Result);
  9541. end;
  9542. procedure TPasResolver.ResetSubScopes(out Depth: integer);
  9543. // move all sub scopes from Scopes to SubScopes
  9544. begin
  9545. Depth:=FSubScopeCount;
  9546. while TopScope is TPasSubScope do
  9547. begin
  9548. {$IFDEF VerbosePasResolver}
  9549. writeln('TPasResolver.ResetSubScopes moving ',TopScope.ClassName,' ScopeCount=',ScopeCount,' SubScopeCount=',FSubScopeCount);
  9550. {$ENDIF}
  9551. if FSubScopeCount=length(FSubScopes) then
  9552. SetLength(FSubScopes,FSubScopeCount+4);
  9553. FSubScopes[FSubScopeCount]:=TopScope;
  9554. inc(FSubScopeCount);
  9555. dec(FScopeCount);
  9556. FScopes[FScopeCount]:=nil;
  9557. if FScopeCount>0 then
  9558. FTopScope:=FScopes[FScopeCount-1]
  9559. else
  9560. FTopScope:=nil;
  9561. end;
  9562. end;
  9563. procedure TPasResolver.RestoreSubScopes(Depth: integer);
  9564. // restore sub scopes
  9565. begin
  9566. while FSubScopeCount>Depth do
  9567. begin
  9568. {$IFDEF VerbosePasResolver}
  9569. writeln('TPasResolver.RestoreSubScopes moving ',FSubScopes[FSubScopeCount-1].ClassName,' ScopeCount=',ScopeCount,' SubScopeCount=',FSubScopeCount);
  9570. {$ENDIF}
  9571. if FScopeCount=length(FScopes) then
  9572. SetLength(FScopes,FScopeCount+4);
  9573. dec(FSubScopeCount);
  9574. FScopes[FScopeCount]:=FSubScopes[FSubScopeCount];
  9575. FTopScope:=FScopes[FScopeCount];
  9576. FSubScopes[FSubScopeCount]:=nil;
  9577. inc(FScopeCount);
  9578. end;
  9579. end;
  9580. procedure TPasResolver.SetLastMsg(const id: int64; MsgType: TMessageType;
  9581. MsgNumber: integer; const Fmt: String; Args: array of const;
  9582. PosEl: TPasElement);
  9583. var
  9584. {$IFDEF VerbosePasResolver}
  9585. s: string;
  9586. {$ENDIF}
  9587. Column, Row: integer;
  9588. begin
  9589. FLastMsgId := id;
  9590. FLastMsgType := MsgType;
  9591. FLastMsgNumber := MsgNumber;
  9592. FLastMsgPattern := Fmt;
  9593. FLastMsg := SafeFormat(Fmt,Args);
  9594. FLastElement := PosEl;
  9595. if PosEl=nil then
  9596. FLastSourcePos:=CurrentParser.CurSourcePos
  9597. else
  9598. begin
  9599. FLastSourcePos.FileName:=PosEl.SourceFilename;
  9600. UnmangleSourceLineNumber(PosEl.SourceLinenumber,Row,Column);
  9601. if Row>=0 then
  9602. FLastSourcePos.Row:=Row
  9603. else
  9604. FLastSourcePos.Row:=0;
  9605. if Column>=0 then
  9606. FLastSourcePos.Column:=Column
  9607. else
  9608. FLastSourcePos.Column:=0;
  9609. end;
  9610. CreateMsgArgs(FLastMsgArgs,Args);
  9611. {$IFDEF VerbosePasResolver}
  9612. write('TPasResolver.SetLastMsg ',id,' ',GetElementSourcePosStr(PosEl),' ');
  9613. s:='';
  9614. str(MsgType,s);
  9615. write(s);
  9616. writeln(': [',MsgNumber,'] ',FLastMsg);
  9617. {$ENDIF}
  9618. end;
  9619. procedure TPasResolver.RaiseMsg(const Id: int64; MsgNumber: integer;
  9620. const Fmt: String; Args: array of const; ErrorPosEl: TPasElement);
  9621. var
  9622. E: EPasResolve;
  9623. begin
  9624. SetLastMsg(Id,mtError,MsgNumber,Fmt,Args,ErrorPosEl);
  9625. E:=EPasResolve.Create(FLastMsg);
  9626. E.Id:=Id;
  9627. E.MsgType:=mtError;
  9628. E.MsgNumber:=MsgNumber;
  9629. E.MsgPattern:=Fmt;
  9630. E.PasElement:=ErrorPosEl;
  9631. E.Args:=FLastMsgArgs;
  9632. E.SourcePos:=FLastSourcePos;
  9633. raise E;
  9634. end;
  9635. procedure TPasResolver.RaiseNotYetImplemented(id: int64; El: TPasElement;
  9636. Msg: string);
  9637. var
  9638. s: String;
  9639. begin
  9640. s:=sNotYetImplemented+' ['+IntToStr(id)+']';
  9641. if Msg<>'' then
  9642. s:=s+' '+Msg;
  9643. {$IFDEF VerbosePasResolver}
  9644. writeln('TPasResolver.RaiseNotYetImplemented s="',s,'" El=',GetObjName(El));
  9645. {$ENDIF}
  9646. RaiseMsg(id,nNotYetImplemented,s,[GetObjName(El)],El);
  9647. end;
  9648. procedure TPasResolver.RaiseInternalError(id: int64; const Msg: string);
  9649. begin
  9650. raise Exception.Create('Internal error: ['+IntToStr(id)+'] '+Msg);
  9651. end;
  9652. procedure TPasResolver.RaiseInvalidScopeForElement(id: int64; El: TPasElement;
  9653. const Msg: string);
  9654. var
  9655. i: Integer;
  9656. s: String;
  9657. begin
  9658. s:='['+IntToStr(id)+'] invalid scope for "'+GetObjName(El)+'": ';
  9659. for i:=0 to ScopeCount-1 do
  9660. begin
  9661. if i>0 then s:=s+',';
  9662. s:=s+Scopes[i].ClassName;
  9663. end;
  9664. if Msg<>'' then
  9665. s:=s+': '+Msg;
  9666. RaiseInternalError(id,s);
  9667. end;
  9668. procedure TPasResolver.RaiseIdentifierNotFound(id: int64; Identifier: string;
  9669. El: TPasElement);
  9670. begin
  9671. {$IFDEF VerbosePasResolver}
  9672. writeln('TPasResolver.RaiseIdentifierNotFound START "',Identifier,'" ErrorEl=',GetObjName(El));
  9673. WriteScopes;
  9674. {$ENDIF}
  9675. RaiseMsg(id,nIdentifierNotFound,sIdentifierNotFound,[Identifier],El);
  9676. end;
  9677. procedure TPasResolver.RaiseXExpectedButYFound(id: int64; const X, Y: string;
  9678. El: TPasElement);
  9679. begin
  9680. RaiseMsg(id,nXExpectedButYFound,sXExpectedButYFound,[X,Y],El);
  9681. end;
  9682. procedure TPasResolver.RaiseConstantExprExp(id: int64; ErrorEl: TPasElement);
  9683. begin
  9684. RaiseMsg(id,nConstantExpressionExpected,sConstantExpressionExpected,[],ErrorEl);
  9685. end;
  9686. procedure TPasResolver.RaiseRangeCheck(id: int64; ErrorEl: TPasElement);
  9687. begin
  9688. RaiseMsg(id,nRangeCheckError,sRangeCheckError,[],ErrorEl);
  9689. end;
  9690. procedure TPasResolver.RaiseIncompatibleTypeDesc(id: int64; MsgNumber: integer;
  9691. const Args: array of const; const GotDesc, ExpDesc: String; ErrorEl: TPasElement);
  9692. function GetString(ArgNo: integer): string;
  9693. begin
  9694. if ArgNo>High(Args) then
  9695. exit('invalid param '+IntToStr(ArgNo));
  9696. case Args[ArgNo].VType of
  9697. vtAnsiString: Result:=AnsiString(Args[ArgNo].VAnsiString);
  9698. else
  9699. Result:='invalid param '+IntToStr(Ord(Args[ArgNo].VType));
  9700. end;
  9701. end;
  9702. begin
  9703. case MsgNumber of
  9704. nIllegalTypeConversionTo:
  9705. RaiseMsg(id,MsgNumber,sIllegalTypeConversionTo,[GotDesc,ExpDesc],ErrorEl);
  9706. nIncompatibleTypesGotExpected:
  9707. RaiseMsg(id,MsgNumber,sIncompatibleTypesGotExpected,[GotDesc,ExpDesc],ErrorEl);
  9708. nIncompatibleTypeArgNo:
  9709. RaiseMsg(id,MsgNumber,sIncompatibleTypeArgNo,[GetString(0),GotDesc,ExpDesc],ErrorEl);
  9710. nIncompatibleTypeArgNoVarParamMustMatchExactly:
  9711. RaiseMsg(id,MsgNumber,sIncompatibleTypeArgNoVarParamMustMatchExactly,
  9712. [GetString(0),GotDesc,ExpDesc],ErrorEl);
  9713. nResultTypeMismatchExpectedButFound:
  9714. RaiseMsg(id,MsgNumber,sResultTypeMismatchExpectedButFound,[GotDesc,ExpDesc],ErrorEl);
  9715. nXExpectedButYFound:
  9716. RaiseMsg(id,MsgNumber,sXExpectedButYFound,[GotDesc,ExpDesc],ErrorEl);
  9717. else
  9718. RaiseInternalError(20170329112911);
  9719. end;
  9720. end;
  9721. procedure TPasResolver.RaiseIncompatibleType(id: int64; MsgNumber: integer;
  9722. const Args: array of const; GotType, ExpType: TPasType; ErrorEl: TPasElement);
  9723. var
  9724. DescA, DescB: String;
  9725. begin
  9726. DescA:=GetTypeDescription(GotType);
  9727. DescB:=GetTypeDescription(ExpType);
  9728. if DescA=DescB then
  9729. begin
  9730. DescA:=GetTypeDescription(GotType,true);
  9731. DescB:=GetTypeDescription(ExpType,true);
  9732. end;
  9733. RaiseIncompatibleTypeDesc(id,MsgNumber,Args,DescA,DescB,ErrorEl);
  9734. end;
  9735. procedure TPasResolver.RaiseIncompatibleTypeRes(id: int64; MsgNumber: integer;
  9736. const Args: array of const; const GotType, ExpType: TPasResolverResult;
  9737. ErrorEl: TPasElement);
  9738. var
  9739. GotDesc, ExpDesc: String;
  9740. begin
  9741. {$IFDEF VerbosePasResolver}
  9742. writeln('TPasResolver.RaiseIncompatibleTypeRes Got={',GetResolverResultDbg(GotType),'} Expected={',GetResolverResultDbg(ExpType),'}');
  9743. {$ENDIF}
  9744. if GotType.BaseType<>ExpType.BaseType then
  9745. begin
  9746. GotDesc:=GetBaseDescription(GotType);
  9747. if ExpType.BaseType=btNil then
  9748. ExpDesc:=BaseTypeNames[btPointer]
  9749. else
  9750. ExpDesc:=GetBaseDescription(ExpType);
  9751. if GotDesc=ExpDesc then
  9752. begin
  9753. GotDesc:=GetBaseDescription(GotType,true);
  9754. ExpDesc:=GetBaseDescription(ExpType,true);
  9755. end;
  9756. end
  9757. else if (GotType.TypeEl<>nil) and (ExpType.TypeEl<>nil) then
  9758. begin
  9759. GotDesc:=GetTypeDescription(GotType);
  9760. ExpDesc:=GetTypeDescription(ExpType);
  9761. if GotDesc=ExpDesc then
  9762. begin
  9763. GotDesc:=GetTypeDescription(GotType,true);
  9764. ExpDesc:=GetTypeDescription(ExpType,true);
  9765. end;
  9766. end
  9767. else
  9768. begin
  9769. GotDesc:=GetResolverResultDescription(GotType,true);
  9770. ExpDesc:=GetResolverResultDescription(ExpType,true);
  9771. if GotDesc=ExpDesc then
  9772. begin
  9773. GotDesc:=GetResolverResultDescription(GotType,false);
  9774. ExpDesc:=GetResolverResultDescription(ExpType,false);
  9775. end;
  9776. end;
  9777. RaiseIncompatibleTypeDesc(id,MsgNumber,Args,GotDesc,ExpDesc,ErrorEl);
  9778. end;
  9779. procedure TPasResolver.RaiseInvalidProcTypeModifier(id: int64;
  9780. ProcType: TPasProcedureType; ptm: TProcTypeModifier; ErrorEl: TPasElement);
  9781. begin
  9782. RaiseMsg(id,nInvalidXModifierY,sInvalidXModifierY,[ProcType.ElementTypeName,
  9783. ProcTypeModifiers[ptm]],ErrorEl);
  9784. end;
  9785. procedure TPasResolver.RaiseInvalidProcModifier(id: int64; Proc: TPasProcedure;
  9786. pm: TProcedureModifier; ErrorEl: TPasElement);
  9787. begin
  9788. RaiseMsg(id,nInvalidXModifierY,sInvalidXModifierY,[Proc.ElementTypeName,
  9789. ModifierNames[pm]],ErrorEl);
  9790. end;
  9791. procedure TPasResolver.LogMsg(const id: int64; MsgType: TMessageType;
  9792. MsgNumber: integer; const Fmt: String; Args: array of const;
  9793. PosEl: TPasElement);
  9794. begin
  9795. SetLastMsg(id,MsgType,MsgNumber,Fmt,Args,PosEl);
  9796. if Assigned(OnLog) then
  9797. OnLog(Self,FLastMsg)
  9798. else if Assigned(CurrentParser.OnLog) then
  9799. CurrentParser.OnLog(Self,FLastMsg);
  9800. end;
  9801. function TPasResolver.CheckCallProcCompatibility(ProcType: TPasProcedureType;
  9802. Params: TParamsExpr; RaiseOnError: boolean; SetReferenceFlags: boolean
  9803. ): integer;
  9804. var
  9805. ProcArgs: TFPList;
  9806. i, ParamCnt, ParamCompatibility: Integer;
  9807. Param: TPasExpr;
  9808. ParamResolved: TPasResolverResult;
  9809. IsVarArgs: Boolean;
  9810. Flags: TPasResolverComputeFlags;
  9811. begin
  9812. Result:=cExact;
  9813. ProcArgs:=ProcType.Args;
  9814. // check args
  9815. ParamCnt:=length(Params.Params);
  9816. IsVarArgs:=false;
  9817. i:=0;
  9818. while i<ParamCnt do
  9819. begin
  9820. Param:=Params.Params[i];
  9821. {$IFDEF VerbosePasResolver}
  9822. writeln('TPasResolver.CheckCallProcCompatibility ',i,'/',ParamCnt);
  9823. {$ENDIF}
  9824. if i<ProcArgs.Count then
  9825. begin
  9826. ParamCompatibility:=CheckParamCompatibility(Param,
  9827. TPasArgument(ProcArgs[i]),i,RaiseOnError,SetReferenceFlags);
  9828. if ParamCompatibility=cIncompatible then
  9829. exit(cIncompatible);
  9830. end
  9831. else
  9832. begin
  9833. IsVarArgs:=IsVarArgs or (ptmVarargs in ProcType.Modifiers);
  9834. if IsVarArgs then
  9835. begin
  9836. Flags:=[rcNoImplicitProcType];
  9837. if SetReferenceFlags then
  9838. Flags:=[rcNoImplicitProcType]
  9839. else
  9840. Flags:=[rcNoImplicitProcType,rcSetReferenceFlags];
  9841. ComputeElement(Param,ParamResolved,Flags,Param);
  9842. if not (rrfReadable in ParamResolved.Flags) then
  9843. begin
  9844. if RaiseOnError then
  9845. RaiseMsg(20170318234957,nVariableIdentifierExpected,
  9846. sVariableIdentifierExpected,[],Param);
  9847. exit(cIncompatible);
  9848. end;
  9849. ParamCompatibility:=cExact;
  9850. end
  9851. else
  9852. begin
  9853. // too many arguments
  9854. if RaiseOnError then
  9855. RaiseMsg(20170216152408,nWrongNumberOfParametersForCallTo,
  9856. sWrongNumberOfParametersForCallTo,[GetProcTypeDescription(ProcType)],Param);
  9857. exit(cIncompatible);
  9858. end;
  9859. end;
  9860. inc(Result,ParamCompatibility);
  9861. inc(i);
  9862. end;
  9863. if (i<ProcArgs.Count) then
  9864. if (TPasArgument(ProcArgs[i]).ValueExpr=nil) then
  9865. begin
  9866. // not enough arguments
  9867. if RaiseOnError then
  9868. // ToDo: position cursor on identifier
  9869. RaiseMsg(20170216152410,nWrongNumberOfParametersForCallTo,
  9870. sWrongNumberOfParametersForCallTo,[GetProcTypeDescription(ProcType)],Params.Value);
  9871. exit(cIncompatible);
  9872. end
  9873. else
  9874. begin
  9875. // the rest are default params
  9876. Result:=cCompatibleWithDefaultParams;
  9877. end;
  9878. end;
  9879. function TPasResolver.CheckCallPropertyCompatibility(PropEl: TPasProperty;
  9880. Params: TParamsExpr; RaiseOnError: boolean): integer;
  9881. var
  9882. PropArg: TPasArgument;
  9883. ArgNo, ParamComp: Integer;
  9884. Param: TPasExpr;
  9885. begin
  9886. Result:=cExact;
  9887. if PropEl.Args.Count<length(Params.Params) then
  9888. begin
  9889. if not RaiseOnError then exit(cIncompatible);
  9890. RaiseMsg(20170216152412,nWrongNumberOfParametersForCallTo,sWrongNumberOfParametersForCallTo,
  9891. [PropEl.Name],Params)
  9892. end
  9893. else if PropEl.Args.Count>length(Params.Params) then
  9894. begin
  9895. if not RaiseOnError then exit(cIncompatible);
  9896. RaiseMsg(20170216152413,nMissingParameterX,sMissingParameterX,
  9897. [TPasArgument(PropEl.Args[length(Params.Params)]).Name],Params);
  9898. end;
  9899. for ArgNo:=0 to PropEl.Args.Count-1 do
  9900. begin
  9901. PropArg:=TPasArgument(PropEl.Args[ArgNo]);
  9902. Param:=Params.Params[ArgNo];
  9903. ParamComp:=CheckParamCompatibility(Param,PropArg,ArgNo,RaiseOnError);
  9904. if ParamComp=cIncompatible then
  9905. exit(cIncompatible);
  9906. inc(Result,ParamComp);
  9907. end;
  9908. end;
  9909. function TPasResolver.CheckCallArrayCompatibility(ArrayEl: TPasArrayType;
  9910. Params: TParamsExpr; RaiseOnError: boolean; EmitHints: boolean): integer;
  9911. var
  9912. ArgNo: Integer;
  9913. Param: TPasExpr;
  9914. ParamResolved: TPasResolverResult;
  9915. procedure GetNextParam;
  9916. begin
  9917. if ArgNo>=length(Params.Params) then
  9918. RaiseMsg(20170216152415,nWrongNumberOfParametersForArray,sWrongNumberOfParametersForArray,
  9919. [],Params);
  9920. Param:=Params.Params[ArgNo];
  9921. ComputeElement(Param,ParamResolved,[]);
  9922. inc(ArgNo);
  9923. end;
  9924. var
  9925. DimNo: integer;
  9926. RangeResolved: TPasResolverResult;
  9927. bt: TResolverBaseType;
  9928. NextType: TPasType;
  9929. RangeExpr: TPasExpr;
  9930. TypeFits: Boolean;
  9931. ParamValue: TResEvalValue;
  9932. begin
  9933. ArgNo:=0;
  9934. repeat
  9935. if length(ArrayEl.Ranges)=0 then
  9936. begin
  9937. // dynamic/open array -> needs exactly one integer
  9938. GetNextParam;
  9939. if (not (rrfReadable in ParamResolved.Flags))
  9940. or not (ParamResolved.BaseType in btAllInteger) then
  9941. exit(CheckRaiseTypeArgNo(20170216152417,ArgNo,Param,ParamResolved,'integer',RaiseOnError));
  9942. if EmitHints then
  9943. begin
  9944. ParamValue:=Eval(Param,[refAutoConst]);
  9945. if ParamValue<>nil then
  9946. try // has const value -> check range
  9947. if (ParamValue.Kind<>revkInt)
  9948. or (TResEvalInt(ParamValue).Int<DynArrayMinIndex)
  9949. or (TResEvalInt(ParamValue).Int>DynArrayMaxIndex) then
  9950. fExprEvaluator.EmitRangeCheckConst(20170520202212,ParamValue.AsString,
  9951. DynArrayMinIndex,DynArrayMaxIndex,Param);
  9952. finally
  9953. ReleaseEvalValue(ParamValue);
  9954. end;
  9955. end;
  9956. end
  9957. else
  9958. begin
  9959. // static array
  9960. for DimNo:=0 to length(ArrayEl.Ranges)-1 do
  9961. begin
  9962. GetNextParam;
  9963. RangeExpr:=ArrayEl.Ranges[DimNo];
  9964. ComputeElement(RangeExpr,RangeResolved,[]);
  9965. bt:=RangeResolved.BaseType;
  9966. if bt=btRange then
  9967. bt:=RangeResolved.SubType;
  9968. if not (rrfReadable in ParamResolved.Flags) then
  9969. begin
  9970. if not RaiseOnError then exit(cIncompatible);
  9971. RaiseIncompatibleTypeRes(20170216152421,nIncompatibleTypeArgNo,
  9972. [IntToStr(ArgNo)],ParamResolved,RangeResolved,Param);
  9973. end;
  9974. TypeFits:=false;
  9975. if (bt in btAllBooleans) and (ParamResolved.BaseType in btAllBooleans) then
  9976. TypeFits:=true
  9977. else if (bt in btAllInteger) and (ParamResolved.BaseType in btAllInteger) then
  9978. TypeFits:=true
  9979. else if (bt in btAllChars) and (ParamResolved.BaseType in btAllChars) then
  9980. TypeFits:=true
  9981. else if (bt=btContext) and (ParamResolved.BaseType=btContext) then
  9982. begin
  9983. if (RangeResolved.TypeEl.ClassType=TPasEnumType)
  9984. and (RangeResolved.TypeEl=ParamResolved.TypeEl) then
  9985. TypeFits:=true
  9986. end;
  9987. if not TypeFits then
  9988. begin
  9989. // incompatible
  9990. if not RaiseOnError then exit(cIncompatible);
  9991. RaiseIncompatibleTypeRes(20170216152422,nIncompatibleTypeArgNo,
  9992. [IntToStr(ArgNo)],ParamResolved,RangeResolved,Param);
  9993. end;
  9994. if EmitHints then
  9995. fExprEvaluator.IsInRange(Param,RangeExpr,true);
  9996. end;
  9997. end;
  9998. if ArgNo=length(Params.Params) then exit(cExact);
  9999. // there are more parameters -> continue in sub array
  10000. NextType:=ResolveAliasType(ArrayEl.ElType);
  10001. if NextType.ClassType<>TPasArrayType then
  10002. RaiseMsg(20170216152424,nWrongNumberOfParametersForArray,sWrongNumberOfParametersForArray,
  10003. [],Params);
  10004. ArrayEl:=TPasArrayType(NextType);
  10005. until false;
  10006. end;
  10007. function TPasResolver.CheckOverloadProcCompatibility(Proc1, Proc2: TPasProcedure
  10008. ): boolean;
  10009. // returns if number and type of arguments fit
  10010. // does not check calling convention
  10011. var
  10012. ProcArgs1, ProcArgs2: TFPList;
  10013. i: Integer;
  10014. begin
  10015. Result:=false;
  10016. ProcArgs1:=Proc1.ProcType.Args;
  10017. ProcArgs2:=Proc2.ProcType.Args;
  10018. {$IFDEF VerbosePasResolver}
  10019. writeln('TPasResolver.CheckOverloadProcCompatibility START Count=',ProcArgs1.Count,' ',ProcArgs2.Count);
  10020. {$ENDIF}
  10021. // check args
  10022. if ProcArgs1.Count<>ProcArgs2.Count then
  10023. exit;
  10024. for i:=0 to ProcArgs1.Count-1 do
  10025. begin
  10026. {$IFDEF VerbosePasResolver}
  10027. writeln('TPasResolver.CheckOverloadProcCompatibility ',i,'/',ProcArgs1.Count);
  10028. {$ENDIF}
  10029. if not CheckProcArgCompatibility(TPasArgument(ProcArgs1[i]),TPasArgument(ProcArgs2[i])) then
  10030. exit;
  10031. end;
  10032. Result:=true;
  10033. end;
  10034. function TPasResolver.CheckProcTypeCompatibility(Proc1,
  10035. Proc2: TPasProcedureType; IsAssign: boolean; ErrorEl: TPasElement;
  10036. RaiseOnIncompatible: boolean): boolean;
  10037. // if RaiseOnIncompatible=true, then Expected=Proc1 Actual=Proc2
  10038. function ModifierError(Modifier: TProcTypeModifier): boolean;
  10039. begin
  10040. Result:=false;
  10041. if not RaiseOnIncompatible then exit;
  10042. RaiseMsg(20170402112049,nXModifierMismatchY,sXModifierMismatchY,
  10043. [Proc1.ElementTypeName,ProcTypeModifiers[Modifier]],ErrorEl);
  10044. end;
  10045. var
  10046. ProcArgs1, ProcArgs2: TFPList;
  10047. i: Integer;
  10048. Result1Resolved, Result2Resolved: TPasResolverResult;
  10049. ExpectedArg, ActualArg: TPasArgument;
  10050. begin
  10051. Result:=false;
  10052. if Proc1.ClassType<>Proc2.ClassType then
  10053. begin
  10054. if RaiseOnIncompatible then
  10055. RaiseXExpectedButYFound(20170402112353,Proc1.ElementTypeName,Proc2.ElementTypeName,ErrorEl);
  10056. exit;
  10057. end;
  10058. if Proc1.IsReferenceTo then
  10059. begin
  10060. if IsAssign then
  10061. // aRefTo:=aproc -> any IsNested/OfObject is allowed
  10062. else
  10063. ; // aRefTo = AnyProc -> ok
  10064. end
  10065. else if Proc2.IsReferenceTo then
  10066. begin
  10067. if IsAssign then
  10068. // NonRefTo := aRefTo -> not possible
  10069. exit(ModifierError(ptmReferenceTo))
  10070. else
  10071. ; // AnyProc = aRefTo -> ok
  10072. end
  10073. else
  10074. begin
  10075. // neither Proc1 nor Proc2 is a reference-to -> check isNested and OfObject
  10076. if Proc1.IsNested<>Proc2.IsNested then
  10077. exit(ModifierError(ptmIsNested));
  10078. if Proc1.IsOfObject<>Proc2.IsOfObject then
  10079. begin
  10080. if (proProcTypeWithoutIsNested in Options) then
  10081. exit(ModifierError(ptmOfObject))
  10082. else if Proc1.IsNested then
  10083. // "is nested" can handle both, proc and method.
  10084. else
  10085. exit(ModifierError(ptmOfObject))
  10086. end;
  10087. end;
  10088. if Proc1.CallingConvention<>Proc2.CallingConvention then
  10089. begin
  10090. if RaiseOnIncompatible then
  10091. RaiseMsg(20170402112253,nCallingConventionMismatch,sCallingConventionMismatch,
  10092. [],ErrorEl);
  10093. exit;
  10094. end;
  10095. ProcArgs1:=Proc1.Args;
  10096. ProcArgs2:=Proc2.Args;
  10097. if ProcArgs1.Count<>ProcArgs2.Count then
  10098. begin
  10099. if RaiseOnIncompatible then
  10100. RaiseMsg(20170902142829,nIncompatibleTypesGotParametersExpected,
  10101. sIncompatibleTypesGotParametersExpected,
  10102. [IntToStr(ProcArgs1.Count),IntToStr(ProcArgs2.Count)],ErrorEl);
  10103. exit;
  10104. end;
  10105. for i:=0 to ProcArgs1.Count-1 do
  10106. begin
  10107. {$IFDEF VerbosePasResolver}
  10108. writeln('TPasResolver.CheckProcAssignCompatibility ',i,'/',ProcArgs1.Count);
  10109. {$ENDIF}
  10110. ExpectedArg:=TPasArgument(ProcArgs1[i]);
  10111. ActualArg:=TPasArgument(ProcArgs2[i]);
  10112. if not CheckProcArgCompatibility(ExpectedArg,ActualArg) then
  10113. begin
  10114. if RaiseOnIncompatible then
  10115. begin
  10116. if ExpectedArg.Access<>ActualArg.Access then
  10117. RaiseMsg(20170404151541,nIncompatibleTypeArgNo,sIncompatibleTypeArgNo,
  10118. [IntToStr(i+1),'access modifier '+AccessDescriptions[ActualArg.Access],
  10119. AccessDescriptions[ExpectedArg.Access]],
  10120. ErrorEl);
  10121. RaiseIncompatibleType(20170404151538,nIncompatibleTypeArgNo,
  10122. [IntToStr(i+1)],ExpectedArg.ArgType,ActualArg.ArgType,ErrorEl);
  10123. end;
  10124. exit;
  10125. end;
  10126. end;
  10127. if Proc1 is TPasFunctionType then
  10128. begin
  10129. ComputeElement(TPasFunctionType(Proc1).ResultEl.ResultType,Result1Resolved,[rcType]);
  10130. ComputeElement(TPasFunctionType(Proc2).ResultEl.ResultType,Result2Resolved,[rcType]);
  10131. if (Result1Resolved.BaseType<>Result2Resolved.BaseType)
  10132. or not IsSameType(Result1Resolved.TypeEl,Result2Resolved.TypeEl) then
  10133. begin
  10134. if RaiseOnIncompatible then
  10135. RaiseIncompatibleTypeRes(20170402112648,nResultTypeMismatchExpectedButFound,
  10136. [],Result1Resolved,Result2Resolved,ErrorEl);
  10137. exit;
  10138. end;
  10139. end;
  10140. Result:=true;
  10141. end;
  10142. function TPasResolver.CheckProcArgCompatibility(Arg1, Arg2: TPasArgument): boolean;
  10143. begin
  10144. Result:=false;
  10145. // check access: var, const, ...
  10146. if Arg1.Access<>Arg2.Access then exit;
  10147. // check untyped
  10148. if Arg1.ArgType=nil then
  10149. exit(Arg2.ArgType=nil);
  10150. if Arg2.ArgType=nil then exit;
  10151. Result:=CheckProcArgTypeCompatibility(Arg1.ArgType,Arg2.ArgType);
  10152. end;
  10153. function TPasResolver.CheckProcArgTypeCompatibility(Arg1, Arg2: TPasType
  10154. ): boolean;
  10155. var
  10156. Arg1Resolved, Arg2Resolved: TPasResolverResult;
  10157. C: TClass;
  10158. Arr1, Arr2: TPasArrayType;
  10159. begin
  10160. ComputeElement(Arg1,Arg1Resolved,[rcType]);
  10161. ComputeElement(Arg2,Arg2Resolved,[rcType]);
  10162. {$IFDEF VerbosePasResolver}
  10163. //writeln('TPasResolver.CheckProcArgTypeCompatibility Arg1=',GetResolverResultDbg(Arg1Resolved),' Arg2=',GetResolverResultDbg(Arg2Resolved));
  10164. {$ENDIF}
  10165. if (Arg1Resolved.BaseType<>Arg2Resolved.BaseType)
  10166. or (Arg1Resolved.TypeEl=nil)
  10167. or (Arg2Resolved.TypeEl=nil) then
  10168. exit(false);
  10169. if (Arg1Resolved.BaseType=Arg2Resolved.BaseType)
  10170. and IsSameType(Arg1Resolved.TypeEl,Arg2Resolved.TypeEl) then
  10171. exit(true);
  10172. C:=Arg1Resolved.TypeEl.ClassType;
  10173. if (C=TPasArrayType) and (Arg2Resolved.TypeEl.ClassType=TPasArrayType) then
  10174. begin
  10175. Arr1:=TPasArrayType(Arg1Resolved.TypeEl);
  10176. Arr2:=TPasArrayType(Arg2Resolved.TypeEl);
  10177. if length(Arr1.Ranges)<>length(Arr2.Ranges) then
  10178. exit(false);
  10179. if length(Arr1.Ranges)>0 then
  10180. RaiseNotYetImplemented(20170328093733,Arr1.Ranges[0],'anonymous static array');
  10181. Result:=CheckProcArgTypeCompatibility(Arr1.ElType,Arr2.ElType);
  10182. exit;
  10183. end;
  10184. Result:=false;
  10185. end;
  10186. function TPasResolver.CheckCanBeLHS(const ResolvedEl: TPasResolverResult;
  10187. ErrorOnFalse: boolean; ErrorEl: TPasElement): boolean;
  10188. var
  10189. El: TPasElement;
  10190. begin
  10191. Result:=false;
  10192. El:=ResolvedEl.IdentEl;
  10193. if El=nil then
  10194. begin
  10195. if ErrorOnFalse then
  10196. begin
  10197. {$IFDEF VerbosePasResolver}
  10198. writeln('TPasResolver.CheckCanBeLHS ',GetResolverResultDbg(ResolvedEl));
  10199. {$ENDIF}
  10200. if (ResolvedEl.TypeEl<>nil) and (ResolvedEl.ExprEl<>nil) then
  10201. RaiseXExpectedButYFound(20170216152727,'identifier',ResolvedEl.TypeEl.ElementTypeName,ResolvedEl.ExprEl)
  10202. else
  10203. RaiseMsg(20170216152426,nVariableIdentifierExpected,sVariableIdentifierExpected,[],ErrorEl);
  10204. end;
  10205. exit;
  10206. end;
  10207. if [rrfWritable,rrfAssignable]*ResolvedEl.Flags<>[] then
  10208. exit(true);
  10209. // not writable
  10210. if not ErrorOnFalse then exit;
  10211. if ResolvedEl.IdentEl is TPasProperty then
  10212. RaiseMsg(20170216152427,nPropertyNotWritable,sPropertyNotWritable,[],ErrorEl)
  10213. else
  10214. RaiseMsg(20170216152429,nVariableIdentifierExpected,sVariableIdentifierExpected,[],ErrorEl);
  10215. end;
  10216. function TPasResolver.CheckAssignCompatibility(const LHS, RHS: TPasElement;
  10217. RaiseOnIncompatible: boolean): integer;
  10218. var
  10219. LeftResolved, RightResolved: TPasResolverResult;
  10220. Flags: TPasResolverComputeFlags;
  10221. IsProcType: Boolean;
  10222. begin
  10223. ComputeElement(LHS,LeftResolved,[rcNoImplicitProc]);
  10224. Flags:=[];
  10225. IsProcType:=IsProcedureType(LeftResolved,true);
  10226. if IsProcType then
  10227. if msDelphi in CurrentParser.CurrentModeswitches then
  10228. Include(Flags,rcNoImplicitProc)
  10229. else
  10230. Include(Flags,rcNoImplicitProcType);
  10231. ComputeElement(RHS,RightResolved,Flags);
  10232. Result:=CheckAssignResCompatibility(LeftResolved,RightResolved,RHS,RaiseOnIncompatible);
  10233. if RHS is TPasExpr then
  10234. CheckAssignExprRange(LeftResolved,TPasExpr(RHS));
  10235. end;
  10236. procedure TPasResolver.CheckAssignExprRange(
  10237. const LeftResolved: TPasResolverResult; RHS: TPasExpr);
  10238. // check if RHS fits into range LeftResolved
  10239. var
  10240. RValue, RangeValue: TResEvalValue;
  10241. MinVal, MaxVal: int64;
  10242. RangeExpr: TBinaryExpr;
  10243. Int: MaxPrecInt;
  10244. C: TClass;
  10245. EnumType: TPasEnumType;
  10246. bt: TResolverBaseType;
  10247. w: WideChar;
  10248. begin
  10249. RValue:=Eval(RHS,[refAutoConst]);
  10250. if RValue=nil then
  10251. exit; // not a const expression
  10252. {$IFDEF VerbosePasResEval}
  10253. writeln('TPasResolver.CheckAssignExprRange Left=',GetResolverResultDbg(LeftResolved),' RValue=',RValue.AsDebugString);
  10254. {$ENDIF}
  10255. RangeValue:=nil;
  10256. try
  10257. if LeftResolved.BaseType=btCustom then
  10258. CheckAssignExprRangeToCustom(LeftResolved,RValue,RHS)
  10259. else if LeftResolved.BaseType=btSet then
  10260. begin
  10261. // assign to a set
  10262. C:=LeftResolved.TypeEl.ClassType;
  10263. if C=TPasRangeType then
  10264. begin
  10265. RangeExpr:=TPasRangeType(LeftResolved.TypeEl).RangeExpr;
  10266. RangeValue:=Eval(RangeExpr,[],false);
  10267. end
  10268. else if C=TPasEnumType then
  10269. begin
  10270. EnumType:=TPasEnumType(LeftResolved.TypeEl);
  10271. RangeValue:=TResEvalRangeInt.CreateValue(revskEnum,EnumType,
  10272. 0,EnumType.Values.Count-1);
  10273. end
  10274. else if C=TPasUnresolvedSymbolRef then
  10275. begin
  10276. // set of basetype
  10277. if LeftResolved.TypeEl.CustomData is TResElDataBaseType then
  10278. begin
  10279. bt:=GetActualBaseType(TResElDataBaseType(LeftResolved.TypeEl.CustomData).BaseType);
  10280. if (bt in (btAllInteger-[btQWord]))
  10281. and GetIntegerRange(bt,MinVal,MaxVal) then
  10282. RangeValue:=TResEvalRangeInt.CreateValue(revskInt,nil,MinVal,MaxVal)
  10283. else if bt=btBoolean then
  10284. RangeValue:=TResEvalRangeInt.CreateValue(revskBool,nil,0,1)
  10285. else if bt=btAnsiChar then
  10286. RangeValue:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ff)
  10287. else if bt=btWideChar then
  10288. RangeValue:=TResEvalRangeInt.CreateValue(revskChar,nil,0,$ffff)
  10289. else
  10290. RaiseNotYetImplemented(20170714205110,RHS);
  10291. end
  10292. else
  10293. RaiseNotYetImplemented(20170714204803,RHS);
  10294. end
  10295. else
  10296. RaiseNotYetImplemented(20170714193100,RHS);
  10297. fExprEvaluator.IsSetCompatible(RValue,RHS,RangeValue,true);
  10298. end
  10299. else if LeftResolved.TypeEl is TPasRangeType then
  10300. begin
  10301. RangeExpr:=TPasRangeType(LeftResolved.TypeEl).RangeExpr;
  10302. RangeValue:=Eval(RangeExpr,[],false);
  10303. if LeftResolved.BaseType=btSet then
  10304. fExprEvaluator.IsSetCompatible(RValue,RHS,RangeValue,true)
  10305. else
  10306. fExprEvaluator.IsInRange(RValue,RHS,RangeValue,RangeExpr,true);
  10307. end
  10308. else if (LeftResolved.BaseType in (btAllInteger-[btQWord]))
  10309. and GetIntegerRange(LeftResolved.BaseType,MinVal,MaxVal) then
  10310. case RValue.Kind of
  10311. revkInt:
  10312. if (MinVal>TResEvalInt(RValue).Int)
  10313. or (MaxVal<TResEvalInt(RValue).Int) then
  10314. fExprEvaluator.EmitRangeCheckConst(20170530093126,
  10315. IntToStr(TResEvalInt(RValue).Int),MinVal,MaxVal,RHS);
  10316. revkUInt:
  10317. if (TResEvalUInt(RValue).UInt>High(MaxPrecInt))
  10318. or (MinVal>MaxPrecInt(TResEvalUInt(RValue).UInt))
  10319. or (MaxVal<MaxPrecInt(TResEvalUInt(RValue).UInt)) then
  10320. fExprEvaluator.EmitRangeCheckConst(20170530093616,
  10321. IntToStr(TResEvalUInt(RValue).UInt),IntToStr(MinVal),IntToStr(MaxVal),RHS);
  10322. revkFloat:
  10323. if TResEvalFloat(RValue).IsInt(Int) then
  10324. begin
  10325. if (MinVal>Int) or (MaxVal<Int) then
  10326. fExprEvaluator.EmitRangeCheckConst(20170802133307,
  10327. IntToStr(Int),MinVal,MaxVal,RHS,mtError);
  10328. end
  10329. else
  10330. begin
  10331. {$IFDEF VerbosePasResEval}
  10332. writeln('TPasResolver.CheckAssignExprRange ',Frac(TResEvalFloat(RValue).FloatValue),' ',TResEvalFloat(RValue).FloatValue<MaxPrecFloat(low(MaxPrecInt)),' ',TResEvalFloat(RValue).FloatValue>MaxPrecFloat(high(MaxPrecInt)),' ',TResEvalFloat(RValue).FloatValue,' ',high(MaxPrecInt));
  10333. {$ENDIF}
  10334. RaiseRangeCheck(20170802133750,RHS);
  10335. end;
  10336. else
  10337. {$IFDEF VerbosePasResEval}
  10338. writeln('TPasResolver.CheckAssignExprRange ',RValue.AsDebugString);
  10339. {$ENDIF}
  10340. RaiseNotYetImplemented(20170530092731,RHS);
  10341. end
  10342. else if LeftResolved.BaseType=btQWord then
  10343. case RValue.Kind of
  10344. revkInt:
  10345. if (TResEvalInt(RValue).Int<0) then
  10346. fExprEvaluator.EmitRangeCheckConst(20170530094316,
  10347. IntToStr(TResEvalUInt(RValue).UInt),'0',IntToStr(High(QWord)),RHS);
  10348. revkUInt: ;
  10349. else
  10350. RaiseNotYetImplemented(20170530094311,RHS);
  10351. end
  10352. else if RValue.Kind in [revkNil,revkBool] then
  10353. // simple type check is enough
  10354. else if LeftResolved.BaseType in [btSingle,btDouble] then
  10355. // simple type check is enough
  10356. // ToDo: warn if precision loss
  10357. else if LeftResolved.BaseType in btAllChars then
  10358. begin
  10359. case RValue.Kind of
  10360. revkString:
  10361. if length(TResEvalString(RValue).S)<>1 then
  10362. begin
  10363. if fExprEvaluator.GetWideChar(TResEvalString(RValue).S,w) then
  10364. Int:=ord(w)
  10365. else
  10366. RaiseXExpectedButYFound(20170714171352,'char','string',RHS);
  10367. end
  10368. else
  10369. Int:=ord(TResEvalString(RValue).S[1]);
  10370. revkUnicodeString:
  10371. if length(TResEvalUTF16(RValue).S)<>1 then
  10372. RaiseXExpectedButYFound(20170714171534,'char','string',RHS)
  10373. else
  10374. Int:=ord(TResEvalUTF16(RValue).S[1]);
  10375. else
  10376. RaiseNotYetImplemented(20170714171218,RHS);
  10377. end;
  10378. case GetActualBaseType(LeftResolved.BaseType) of
  10379. btAnsiChar: MaxVal:=$ff;
  10380. btWideChar: MaxVal:=$ffff;
  10381. end;
  10382. if (Int>MaxVal) then
  10383. fExprEvaluator.EmitRangeCheckConst(20170714171911,
  10384. '#'+IntToStr(Int),'#0','#'+IntToStr(MaxVal),RHS);
  10385. end
  10386. else if LeftResolved.BaseType in btAllStrings then
  10387. // simple type check is enough
  10388. // ToDo: warn if unicode to non-utf8
  10389. else if LeftResolved.BaseType=btContext then
  10390. // simple type check is enough
  10391. else
  10392. begin
  10393. {$IFDEF VerbosePasResolver}
  10394. writeln('TPasResolver.CheckAssignExprRange LeftResolved=',GetResolverResultDbg(LeftResolved));
  10395. {$ENDIF}
  10396. RaiseNotYetImplemented(20170530095243,RHS);
  10397. end;
  10398. finally
  10399. ReleaseEvalValue(RValue);
  10400. ReleaseEvalValue(RangeValue);
  10401. end;
  10402. end;
  10403. procedure TPasResolver.CheckAssignExprRangeToCustom(
  10404. const LeftResolved: TPasResolverResult; RValue: TResEvalValue; RHS: TPasExpr);
  10405. begin
  10406. if LeftResolved.BaseType<>btCustom then exit;
  10407. if RValue=nil then exit;
  10408. if RHS=nil then ;
  10409. end;
  10410. function TPasResolver.CheckAssignResCompatibility(const LHS,
  10411. RHS: TPasResolverResult; ErrorEl: TPasElement; RaiseOnIncompatible: boolean
  10412. ): integer;
  10413. var
  10414. TypeEl: TPasType;
  10415. Handled: Boolean;
  10416. C: TClass;
  10417. LBT, RBT: TResolverBaseType;
  10418. begin
  10419. // check if the RHS can be converted to LHS
  10420. {$IFDEF VerbosePasResolver}
  10421. writeln('TPasResolver.CheckAssignResCompatibility START LHS='+GetResolverResultDbg(LHS)+' RHS='+GetResolverResultDbg(RHS));
  10422. {$ENDIF}
  10423. Result:=-1;
  10424. Handled:=false;
  10425. Result:=CheckAssignCompatibilityCustom(LHS,RHS,ErrorEl,RaiseOnIncompatible,Handled);
  10426. if Handled and (Result>=cExact) and (Result<cIncompatible) then
  10427. exit;
  10428. if not Handled then
  10429. begin
  10430. LBT:=GetActualBaseType(LHS.BaseType);
  10431. RBT:=GetActualBaseType(RHS.BaseType);
  10432. if LHS.TypeEl=nil then
  10433. begin
  10434. if LBT=btUntyped then
  10435. begin
  10436. // untyped parameter
  10437. Result:=cTypeConversion;
  10438. end
  10439. else
  10440. RaiseNotYetImplemented(20160922163631,LHS.IdentEl);
  10441. end
  10442. else if LBT=RBT then
  10443. begin
  10444. if LBT=btContext then
  10445. exit(CheckAssignCompatibilityUserType(LHS,RHS,ErrorEl,RaiseOnIncompatible))
  10446. else
  10447. Result:=cExact; // same base type, maybe not same type name (e.g. longint and integer)
  10448. end
  10449. else if (LBT in btAllBooleans)
  10450. and (RBT in btAllBooleans) then
  10451. Result:=cCompatible
  10452. else if (LBT in btAllChars)
  10453. and (RBT in btAllChars) then
  10454. case LBT of
  10455. btAnsiChar:
  10456. Result:=cLossyConversion;
  10457. btWideChar:
  10458. if RBT=btAnsiChar then
  10459. Result:=cCompatible
  10460. else
  10461. Result:=cLossyConversion;
  10462. else
  10463. RaiseNotYetImplemented(20170728132440,ErrorEl,BaseTypeNames[LBT]);
  10464. end
  10465. else if (LBT in btAllStrings)
  10466. and (RBT in btAllStringAndChars) then
  10467. case LBT of
  10468. btAnsiString:
  10469. if RBT in [btAnsiChar,btShortString,btRawByteString] then
  10470. Result:=cCompatible
  10471. else
  10472. Result:=cLossyConversion;
  10473. btShortString:
  10474. if RBT=btAnsiChar then
  10475. Result:=cCompatible
  10476. else
  10477. Result:=cLossyConversion;
  10478. btWideString,btUnicodeString:
  10479. Result:=cCompatible;
  10480. btRawByteString:
  10481. if RBT in [btAnsiChar,btAnsiString,btShortString] then
  10482. Result:=cCompatible
  10483. else
  10484. Result:=cLossyConversion;
  10485. else
  10486. RaiseNotYetImplemented(20170417195208,ErrorEl,BaseTypeNames[LBT]);
  10487. end
  10488. else if (LBT in btAllInteger)
  10489. and (RBT in btAllInteger) then
  10490. begin
  10491. Result:=cIntToIntConversion+ord(LBT)-ord(RBT);
  10492. case LBT of
  10493. btByte,
  10494. btShortInt: inc(Result,cLossyConversion);
  10495. btWord,
  10496. btSmallInt:
  10497. if not (RBT in [btByte,btShortInt]) then
  10498. inc(Result,cLossyConversion);
  10499. btUIntSingle:
  10500. if not (RBT in [btByte,btShortInt,btWord,btSmallInt]) then
  10501. inc(Result,cLossyConversion);
  10502. btIntSingle:
  10503. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,btUIntSingle]) then
  10504. inc(Result,cLossyConversion);
  10505. btLongWord,
  10506. btLongint:
  10507. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,btUIntSingle,btIntSingle]) then
  10508. inc(Result,cLossyConversion);
  10509. btUIntDouble:
  10510. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,btLongWord,btLongint]) then
  10511. inc(Result,cLossyConversion);
  10512. btIntDouble:
  10513. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,btLongWord,btLongint,btUIntDouble]) then
  10514. inc(Result,cLossyConversion);
  10515. btQWord,
  10516. btInt64,btComp:
  10517. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,btUIntSingle,btIntSingle,
  10518. btLongWord,btLongint,btUIntDouble,btIntDouble]) then
  10519. inc(Result,cLossyConversion);
  10520. else
  10521. RaiseNotYetImplemented(20170417205301,ErrorEl,BaseTypeNames[LBT]);
  10522. end;
  10523. end
  10524. else if (LBT in btAllFloats)
  10525. and (RBT in (btAllFloats+btAllInteger)) then
  10526. begin
  10527. Result:=cToFloatConversion+ord(LBT)-ord(RBT);
  10528. case LBT of
  10529. btSingle:
  10530. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,
  10531. btIntSingle,btUIntSingle]) then
  10532. inc(Result,cLossyConversion);
  10533. btDouble:
  10534. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,
  10535. btIntSingle,btUIntSingle,btSingle,
  10536. btLongWord,btLongint,
  10537. btIntDouble,btUIntDouble]) then
  10538. inc(Result,cLossyConversion);
  10539. btExtended,btCExtended:
  10540. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,
  10541. btIntSingle,btUIntSingle,btSingle,
  10542. btLongWord,btLongint,
  10543. btInt64,btComp,
  10544. btIntDouble,btUIntDouble,btDouble]) then
  10545. inc(Result,cLossyConversion);
  10546. btCurrency:
  10547. if not (RBT in [btByte,btShortInt,btWord,btSmallInt,
  10548. btIntSingle,btUIntSingle,
  10549. btLongWord,btLongint]) then
  10550. inc(Result,cLossyConversion);
  10551. else
  10552. RaiseNotYetImplemented(20170417205910,ErrorEl,BaseTypeNames[LBT]);
  10553. end;
  10554. end
  10555. else if LBT=btNil then
  10556. begin
  10557. if RaiseOnIncompatible then
  10558. RaiseMsg(20170216152431,nCantAssignValuesToAnAddress,sCantAssignValuesToAnAddress,
  10559. [],ErrorEl);
  10560. exit(cIncompatible);
  10561. end
  10562. else if LBT in [btRange,btSet,btModule,btProc] then
  10563. begin
  10564. if RaiseOnIncompatible then
  10565. RaiseMsg(20170216152432,nIllegalExpression,sIllegalExpression,[],ErrorEl);
  10566. exit(cIncompatible);
  10567. end
  10568. else if (LHS.IdentEl=nil) and (LHS.ExprEl=nil) then
  10569. begin
  10570. if RaiseOnIncompatible then
  10571. RaiseMsg(20170216152434,nIllegalExpression,sIllegalExpression,[],ErrorEl);
  10572. exit(cIncompatible);
  10573. end
  10574. else if RBT=btNil then
  10575. begin
  10576. if LBT=btPointer then
  10577. Result:=cExact
  10578. else if LBT=btContext then
  10579. begin
  10580. TypeEl:=LHS.TypeEl;
  10581. C:=TypeEl.ClassType;
  10582. if (C=TPasClassType)
  10583. or (C=TPasClassOfType)
  10584. or (C=TPasPointerType)
  10585. or C.InheritsFrom(TPasProcedureType)
  10586. or IsDynArray(TypeEl) then
  10587. Result:=cExact;
  10588. end;
  10589. end
  10590. else if (LBT=btSet) and (RBT=btSet) then
  10591. begin
  10592. if RHS.TypeEl=nil then
  10593. Result:=cExact // empty set
  10594. else if (LHS.SubType=RHS.SubType) and (LHS.SubType in (btAllBooleans+btAllInteger+btAllChars)) then
  10595. Result:=cExact
  10596. else if ((LHS.SubType in btAllBooleans) and (RHS.SubType in btAllBooleans))
  10597. or ((LHS.SubType in btAllInteger) and (RHS.SubType in btAllInteger)) then
  10598. Result:=cCompatible
  10599. else if (LHS.SubType=btContext) and (LHS.TypeEl is TPasEnumType)
  10600. and (LHS.TypeEl=RHS.TypeEl) then
  10601. Result:=cExact;
  10602. end
  10603. else if RBT=btProc then
  10604. begin
  10605. if (msDelphi in CurrentParser.CurrentModeswitches)
  10606. and (LHS.TypeEl is TPasProcedureType)
  10607. and (RHS.IdentEl is TPasProcedure) then
  10608. begin
  10609. // for example ProcVar:=Proc
  10610. if CheckProcTypeCompatibility(TPasProcedureType(LHS.TypeEl),
  10611. TPasProcedure(RHS.IdentEl).ProcType,true,ErrorEl,RaiseOnIncompatible) then
  10612. exit(cExact);
  10613. end;
  10614. end
  10615. else if LBT=btPointer then
  10616. begin
  10617. if RBT=btPointer then
  10618. begin
  10619. if IsBaseType(LHS.TypeEl,btPointer) then
  10620. Result:=cExact // btPointer can take any pointer
  10621. else if IsBaseType(RHS.TypeEl,btPointer) then
  10622. Result:=cTypeConversion // any pointer can take a btPointer
  10623. else if IsSameType(LHS.TypeEl,RHS.TypeEl) then
  10624. Result:=cExact // pointer of same type
  10625. else if (LHS.TypeEl.ClassType=TPasPointerType)
  10626. and (RHS.TypeEl.ClassType=TPasPointerType) then
  10627. Result:=CheckAssignCompatibility(TPasPointerType(LHS.TypeEl).DestType,
  10628. TPasPointerType(RHS.TypeEl).DestType,RaiseOnIncompatible);
  10629. end
  10630. else if IsBaseType(LHS.TypeEl,btPointer) then
  10631. begin
  10632. if RBT=btContext then
  10633. begin
  10634. C:=RHS.TypeEl.ClassType;
  10635. if C=TPasClassType then
  10636. exit(cTypeConversion) // class type or class instance
  10637. else if C=TPasClassOfType then
  10638. Result:=cTypeConversion
  10639. else if C=TPasArrayType then
  10640. begin
  10641. if IsDynArray(RHS.TypeEl) then
  10642. Result:=cTypeConversion;
  10643. end
  10644. else if (C=TPasProcedureType) or (C=TPasFunctionType) then
  10645. // pointer:=procvar
  10646. Result:=cLossyConversion;
  10647. end;
  10648. end;
  10649. end
  10650. else if (LBT=btContext) and (LHS.TypeEl is TPasArrayType) then
  10651. Result:=CheckAssignCompatibilityArrayType(LHS,RHS,ErrorEl,RaiseOnIncompatible);
  10652. end;
  10653. if (Result>=0) and (Result<cIncompatible) then
  10654. begin
  10655. // type fits -> check readable
  10656. if not (rrfReadable in RHS.Flags) then
  10657. begin
  10658. if RaiseOnIncompatible then
  10659. begin
  10660. {$IFDEF VerbosePasResolver}
  10661. writeln('TPasResolver.CheckAssignResCompatibility RHS not readable. LHS='+GetResolverResultDbg(LHS)+' RHS='+GetResolverResultDbg(RHS));
  10662. {$ENDIF}
  10663. RaiseMsg(20170318235637,nVariableIdentifierExpected,
  10664. sVariableIdentifierExpected,[],ErrorEl);
  10665. end;
  10666. exit(cIncompatible);
  10667. end;
  10668. exit;
  10669. end;
  10670. // incompatible
  10671. {$IFDEF VerbosePasResolver}
  10672. writeln('TPasResolver.CheckAssignResCompatibility incompatible LHS='+GetResolverResultDbg(LHS)+' RHS='+GetResolverResultDbg(RHS));
  10673. {$ENDIF}
  10674. if not RaiseOnIncompatible then
  10675. exit(cIncompatible);
  10676. // create error messages
  10677. RaiseIncompatibleTypeRes(20170216152437,nIncompatibleTypesGotExpected,
  10678. [],RHS,LHS,ErrorEl);
  10679. end;
  10680. function TPasResolver.CheckEqualElCompatibility(Left, Right: TPasElement;
  10681. ErrorEl: TPasElement; RaiseOnIncompatible: boolean; SetReferenceFlags: boolean
  10682. ): integer;
  10683. // check if the RightResolved is type compatible to LeftResolved
  10684. var
  10685. LFlags, RFlags: TPasResolverComputeFlags;
  10686. LeftResolved, RightResolved: TPasResolverResult;
  10687. LeftErrorEl, RightErrorEl: TPasElement;
  10688. begin
  10689. Result:=cIncompatible;
  10690. // Delphi resolves both sides, so it forbids "if procvar=procvar then"
  10691. // FPC is more clever. It supports "if procvar=@proc then", "function=value"
  10692. if msDelphi in CurrentParser.CurrentModeswitches then
  10693. LFlags:=[]
  10694. else
  10695. LFlags:=[rcNoImplicitProcType];
  10696. if SetReferenceFlags then
  10697. Include(LFlags,rcSetReferenceFlags);
  10698. ComputeElement(Left,LeftResolved,LFlags);
  10699. if (msDelphi in CurrentParser.CurrentModeswitches) then
  10700. RFlags:=LFlags
  10701. else
  10702. begin
  10703. if LeftResolved.BaseType=btNil then
  10704. RFlags:=[rcNoImplicitProcType]
  10705. else if IsProcedureType(LeftResolved,true) then
  10706. RFlags:=[rcNoImplicitProcType]
  10707. else
  10708. RFlags:=[];
  10709. end;
  10710. if SetReferenceFlags then
  10711. Include(RFlags,rcSetReferenceFlags);
  10712. {$IFDEF VerbosePasResolver}
  10713. writeln('TPasResolver.CheckEqualElCompatibility LFlags=',dbgs(LFlags),' Left=',GetResolverResultDbg(LeftResolved),' Delphi=',msDelphi in CurrentParser.CurrentModeswitches,' RFlags=',dbgs(RFlags));
  10714. {$ENDIF}
  10715. ComputeElement(Right,RightResolved,RFlags);
  10716. if ErrorEl=nil then
  10717. begin
  10718. LeftErrorEl:=Left;
  10719. RightErrorEl:=Right;
  10720. end
  10721. else
  10722. begin
  10723. LeftErrorEl:=ErrorEl;
  10724. RightErrorEl:=ErrorEl;
  10725. end;
  10726. Result:=CheckEqualResCompatibility(LeftResolved,RightResolved,LeftErrorEl,
  10727. RaiseOnIncompatible,RightErrorEl);
  10728. end;
  10729. function TPasResolver.CheckEqualResCompatibility(const LHS,
  10730. RHS: TPasResolverResult; LErrorEl: TPasElement; RaiseOnIncompatible: boolean;
  10731. RErrorEl: TPasElement): integer;
  10732. var
  10733. TypeEl: TPasType;
  10734. ok: Boolean;
  10735. begin
  10736. Result:=cIncompatible;
  10737. if RErrorEl=nil then RErrorEl:=LErrorEl;
  10738. // check if the RHS is type compatible to LHS
  10739. {$IFDEF VerbosePasResolver}
  10740. writeln('TPasResolver.CheckEqualResCompatibility LHS=',GetResolverResultDbg(LHS),' RHS=',GetResolverResultDbg(RHS));
  10741. {$ENDIF}
  10742. if not (rrfReadable in LHS.Flags) then
  10743. begin
  10744. ok:=false;
  10745. if (LHS.BaseType=btContext) and (LHS.TypeEl.ClassType=TPasClassType)
  10746. and (LHS.IdentEl=LHS.TypeEl) then
  10747. begin
  10748. if RHS.BaseType=btNil then
  10749. ok:=true
  10750. else if (RHS.BaseType=btContext) and (RHS.TypeEl.ClassType=TPasClassOfType)
  10751. and (rrfReadable in RHS.Flags) then
  10752. // for example if TImage=ImageClass then
  10753. ok:=true;
  10754. end;
  10755. if not ok then
  10756. RaiseMsg(20170216152438,nNotReadable,sNotReadable,[],LErrorEl);
  10757. end;
  10758. if not (rrfReadable in RHS.Flags) then
  10759. begin
  10760. ok:=false;
  10761. if (RHS.BaseType=btContext) and (RHS.TypeEl.ClassType=TPasClassType)
  10762. and (RHS.IdentEl=RHS.TypeEl) then
  10763. begin
  10764. if LHS.BaseType=btNil then
  10765. ok:=true
  10766. else if (LHS.BaseType=btContext) and (LHS.TypeEl.ClassType=TPasClassOfType)
  10767. and (rrfReadable in LHS.Flags) then
  10768. // for example if ImageClass=TImage then
  10769. ok:=true;
  10770. end;
  10771. if not ok then
  10772. RaiseMsg(20170216152440,nNotReadable,sNotReadable,[],RErrorEl);
  10773. end;
  10774. if (LHS.BaseType=btCustom) or (RHS.BaseType=btCustom) then
  10775. begin
  10776. Result:=CheckEqualCompatibilityCustomType(LHS,RHS,LErrorEl,RaiseOnIncompatible);
  10777. if (Result=cIncompatible) and RaiseOnIncompatible then
  10778. RaiseIncompatibleTypeRes(20170330010727,nIncompatibleTypesGotExpected,
  10779. [],RHS,LHS,LErrorEl);
  10780. exit;
  10781. end
  10782. else if LHS.BaseType=RHS.BaseType then
  10783. begin
  10784. if LHS.BaseType=btContext then
  10785. exit(CheckEqualCompatibilityUserType(LHS,RHS,LErrorEl,RaiseOnIncompatible))
  10786. else
  10787. exit(cExact); // same base type, maybe not same type name (e.g. longint and integer)
  10788. end
  10789. else if (LHS.BaseType in btAllInteger+btAllFloats)
  10790. and (RHS.BaseType in btAllInteger+btAllFloats) then
  10791. exit(cCompatible)
  10792. else if (LHS.BaseType in btAllBooleans)
  10793. and (RHS.BaseType in btAllBooleans) then
  10794. exit(cCompatible)
  10795. else if (LHS.BaseType in btAllStringAndChars)
  10796. and (RHS.BaseType in btAllStringAndChars) then
  10797. exit(cCompatible)
  10798. else if LHS.BaseType=btNil then
  10799. begin
  10800. if RHS.BaseType in [btPointer,btNil] then
  10801. exit(cExact)
  10802. else if RHS.BaseType=btContext then
  10803. begin
  10804. TypeEl:=RHS.TypeEl;
  10805. if (TypeEl.ClassType=TPasClassType)
  10806. or (TypeEl.ClassType=TPasClassOfType)
  10807. or (TypeEl.ClassType=TPasPointerType)
  10808. or (TypeEl is TPasProcedureType)
  10809. or IsDynArray(TypeEl) then
  10810. exit(cExact);
  10811. end;
  10812. if RaiseOnIncompatible then
  10813. RaiseIncompatibleTypeRes(20170216152442,nIncompatibleTypesGotExpected,
  10814. [],RHS,LHS,RErrorEl)
  10815. else
  10816. exit(cIncompatible);
  10817. end
  10818. else if RHS.BaseType=btNil then
  10819. begin
  10820. if LHS.BaseType=btPointer then
  10821. exit(cExact)
  10822. else if LHS.BaseType=btContext then
  10823. begin
  10824. TypeEl:=LHS.TypeEl;
  10825. if (TypeEl.ClassType=TPasClassType)
  10826. or (TypeEl.ClassType=TPasClassOfType)
  10827. or (TypeEl.ClassType=TPasPointerType)
  10828. or (TypeEl is TPasProcedureType)
  10829. or IsDynArray(TypeEl) then
  10830. exit(cExact);
  10831. end;
  10832. if RaiseOnIncompatible then
  10833. RaiseIncompatibleTypeRes(20170216152444,nIncompatibleTypesGotExpected,
  10834. [],LHS,RHS,LErrorEl)
  10835. else
  10836. exit(cIncompatible);
  10837. end
  10838. else if LHS.BaseType=btSet then
  10839. begin
  10840. if RHS.BaseType=btSet then
  10841. begin
  10842. if LHS.TypeEl=nil then
  10843. exit(cExact); // empty set
  10844. if RHS.TypeEl=nil then
  10845. exit(cExact); // empty set
  10846. if LHS.TypeEl=RHS.TypeEl then
  10847. exit(cExact);
  10848. if (LHS.SubType=RHS.SubType) and (LHS.SubType in (btAllBooleans+btAllInteger+btAllChars)) then
  10849. exit(cExact);
  10850. if ((LHS.SubType in btAllBooleans) and (RHS.SubType in btAllBooleans))
  10851. or ((LHS.SubType in btAllInteger) and (RHS.SubType in btAllInteger)) then
  10852. exit(cCompatible);
  10853. if RaiseOnIncompatible then
  10854. RaiseMsg(20170216152446,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  10855. ['set of '+BaseTypeNames[LHS.SubType],'set of '+BaseTypeNames[RHS.SubType]],LErrorEl)
  10856. else
  10857. exit(cIncompatible);
  10858. end;
  10859. end
  10860. else if RaiseOnIncompatible then
  10861. RaiseIncompatibleTypeRes(20170216152449,nIncompatibleTypesGotExpected,
  10862. [],RHS,LHS,RErrorEl)
  10863. else
  10864. exit(cIncompatible);
  10865. RaiseNotYetImplemented(20161007101041,LErrorEl,'LHS='+GetResolverResultDbg(LHS)+' RHS='+GetResolverResultDbg(RHS));
  10866. end;
  10867. function TPasResolver.ResolvedElCanBeVarParam(
  10868. const ResolvedEl: TPasResolverResult): boolean;
  10869. begin
  10870. Result:=false;
  10871. if [rrfReadable,rrfWritable]*ResolvedEl.Flags<>[rrfReadable,rrfWritable] then
  10872. exit;
  10873. if ResolvedEl.IdentEl=nil then exit;
  10874. if ResolvedEl.IdentEl.ClassType=TPasVariable then
  10875. exit(true);
  10876. if (ResolvedEl.IdentEl.ClassType=TPasArgument) then
  10877. begin
  10878. Result:=(TPasArgument(ResolvedEl.IdentEl).Access in [argDefault, argVar, argOut]);
  10879. exit;
  10880. end;
  10881. if ResolvedEl.IdentEl.ClassType=TPasResultElement then
  10882. exit(true);
  10883. if (ResolvedEl.IdentEl.ClassType=TPasConst) then
  10884. begin
  10885. // typed const are writable
  10886. Result:=(TPasConst(ResolvedEl.IdentEl).VarType<>nil);
  10887. exit;
  10888. end;
  10889. if (proPropertyAsVarParam in Options)
  10890. and (ResolvedEl.IdentEl.ClassType=TPasProperty) then
  10891. exit(true);
  10892. end;
  10893. function TPasResolver.ResolvedElIsClassInstance(
  10894. const ResolvedEl: TPasResolverResult): boolean;
  10895. begin
  10896. Result:=false;
  10897. if ResolvedEl.BaseType<>btContext then exit;
  10898. if ResolvedEl.TypeEl=nil then exit;
  10899. if ResolvedEl.TypeEl.ClassType<>TPasClassType then exit;
  10900. if (ResolvedEl.IdentEl is TPasVariable)
  10901. or (ResolvedEl.IdentEl.ClassType=TPasArgument)
  10902. or (ResolvedEl.IdentEl.ClassType=TPasResultElement) then
  10903. exit(true);
  10904. end;
  10905. function TPasResolver.GetProcTypeDescription(ProcType: TPasProcedureType;
  10906. UseName: boolean; AddPaths: boolean): string;
  10907. var
  10908. Args: TFPList;
  10909. i: Integer;
  10910. Arg: TPasArgument;
  10911. begin
  10912. if ProcType=nil then exit('nil');
  10913. Result:=ProcType.TypeName;
  10914. if ProcType.IsReferenceTo then
  10915. Result:=ProcTypeModifiers[ptmReferenceTo]+' '+Result;
  10916. if UseName and (ProcType.Parent is TPasProcedure) then
  10917. begin
  10918. if AddPaths then
  10919. Result:=Result+' '+ProcType.Parent.FullName
  10920. else
  10921. Result:=Result+' '+ProcType.Parent.Name;
  10922. end;
  10923. Args:=ProcType.Args;
  10924. if Args.Count>0 then
  10925. begin
  10926. Result:=Result+'(';
  10927. for i:=0 to Args.Count-1 do
  10928. begin
  10929. if i>0 then Result:=Result+';';
  10930. Arg:=TPasArgument(Args[i]);
  10931. if AccessNames[Arg.Access]<>'' then
  10932. Result:=Result+AccessNames[Arg.Access];
  10933. if Arg.ArgType=nil then
  10934. Result:=Result+'untyped'
  10935. else
  10936. Result:=Result+GetTypeDescription(Arg.ArgType,AddPaths);
  10937. end;
  10938. Result:=Result+')';
  10939. end;
  10940. if ProcType.IsOfObject then
  10941. Result:=Result+' '+ProcTypeModifiers[ptmOfObject];
  10942. if ProcType.IsNested then
  10943. Result:=Result+' '+ProcTypeModifiers[ptmIsNested];
  10944. if cCallingConventions[ProcType.CallingConvention]<>'' then
  10945. Result:=Result+';'+cCallingConventions[ProcType.CallingConvention];
  10946. end;
  10947. function TPasResolver.GetResolverResultDescription(const T: TPasResolverResult;
  10948. OnlyType: boolean): string;
  10949. function GetSubTypeName: string;
  10950. begin
  10951. if (T.TypeEl<>nil) and (T.TypeEl.Name<>'') then
  10952. Result:=T.TypeEl.Name
  10953. else
  10954. Result:=BaseTypeNames[T.SubType];
  10955. end;
  10956. var
  10957. ArrayEl: TPasArrayType;
  10958. begin
  10959. case T.BaseType of
  10960. btModule: exit(T.IdentEl.ElementTypeName+' '+T.IdentEl.Name);
  10961. btNil: exit('nil');
  10962. btRange:
  10963. Result:='range of '+GetSubTypeName;
  10964. btSet:
  10965. Result:='set/array literal of '+GetSubTypeName;
  10966. btContext:
  10967. begin
  10968. if T.TypeEl.ClassType=TPasClassOfType then
  10969. Result:='class of '+TPasClassOfType(T.TypeEl).DestType.Name
  10970. else if T.TypeEl.ClassType=TPasAliasType then
  10971. Result:=TPasAliasType(T.TypeEl).DestType.Name
  10972. else if T.TypeEl.ClassType=TPasTypeAliasType then
  10973. Result:='type '+TPasAliasType(T.TypeEl).DestType.Name
  10974. else if T.TypeEl.ClassType=TPasArrayType then
  10975. begin
  10976. ArrayEl:=TPasArrayType(T.TypeEl);
  10977. if length(ArrayEl.Ranges)=0 then
  10978. Result:='array of '+ArrayEl.ElType.Name
  10979. else
  10980. Result:='static array[] of '+ArrayEl.ElType.Name;
  10981. end
  10982. else if T.TypeEl is TPasProcedureType then
  10983. Result:=GetProcTypeDescription(TPasProcedureType(T.TypeEl),false)
  10984. else if T.TypeEl.Name<>'' then
  10985. Result:=T.TypeEl.Name
  10986. else
  10987. Result:=T.TypeEl.ElementTypeName;
  10988. end;
  10989. btCustom:
  10990. Result:=T.TypeEl.Name;
  10991. else
  10992. Result:=BaseTypeNames[T.BaseType];
  10993. end;
  10994. if (not OnlyType) and (T.TypeEl<>T.IdentEl) and (T.IdentEl<>nil) then
  10995. Result:=T.IdentEl.Name+':'+Result;
  10996. end;
  10997. function TPasResolver.GetTypeDescription(aType: TPasType; AddPath: boolean): string;
  10998. function GetName: string;
  10999. var
  11000. s: String;
  11001. begin
  11002. Result:=aType.Name;
  11003. if Result='' then
  11004. Result:=aType.ElementTypeName;
  11005. if AddPath then
  11006. begin
  11007. s:=aType.FullPath;
  11008. if (s<>'') and (s<>'.') then
  11009. Result:=s+'.'+Result;
  11010. end;
  11011. end;
  11012. var
  11013. C: TClass;
  11014. begin
  11015. if aType=nil then exit('untyped');
  11016. C:=aType.ClassType;
  11017. if (C=TPasUnresolvedSymbolRef) then
  11018. begin
  11019. Result:=GetName;
  11020. if TPasUnresolvedSymbolRef(aType).CustomData is TResElDataBuiltInProc then
  11021. Result:=Result+'()';
  11022. exit;
  11023. end
  11024. else if (C=TPasUnresolvedTypeRef) then
  11025. Result:=GetName
  11026. else
  11027. Result:=GetName;
  11028. end;
  11029. function TPasResolver.GetTypeDescription(const R: TPasResolverResult;
  11030. AddPath: boolean): string;
  11031. begin
  11032. Result:=GetTypeDescription(R.TypeEl,AddPath);
  11033. if R.IdentEl=R.TypeEl then
  11034. begin
  11035. if R.TypeEl.ElementTypeName<>'' then
  11036. Result:=R.TypeEl.ElementTypeName+' '+Result
  11037. else
  11038. Result:='type '+Result;
  11039. end;
  11040. end;
  11041. function TPasResolver.GetBaseDescription(const R: TPasResolverResult;
  11042. AddPath: boolean): string;
  11043. begin
  11044. if R.BaseType=btContext then
  11045. Result:=GetTypeDescription(R,AddPath)
  11046. else
  11047. Result:=BaseTypeNames[R.BaseType];
  11048. end;
  11049. function TPasResolver.GetPasPropertyType(El: TPasProperty): TPasType;
  11050. begin
  11051. Result:=nil;
  11052. while El<>nil do
  11053. begin
  11054. if El.VarType<>nil then
  11055. exit(El.VarType);
  11056. El:=GetPasPropertyAncestor(El);
  11057. end;
  11058. end;
  11059. function TPasResolver.GetPasPropertyAncestor(El: TPasProperty;
  11060. WithRedeclarations: boolean): TPasProperty;
  11061. begin
  11062. Result:=nil;
  11063. if El=nil then exit;
  11064. if (not WithRedeclarations) and (El.VarType<>nil) then exit;
  11065. if El.CustomData=nil then exit;
  11066. Result:=TPasPropertyScope(El.CustomData).AncestorProp;
  11067. end;
  11068. function TPasResolver.GetPasPropertyGetter(El: TPasProperty): TPasElement;
  11069. // search the member variable or getter function of a property
  11070. var
  11071. DeclEl: TPasElement;
  11072. begin
  11073. Result:=nil;
  11074. while El<>nil do
  11075. begin
  11076. if El.ReadAccessor<>nil then
  11077. begin
  11078. DeclEl:=(El.ReadAccessor.CustomData as TResolvedReference).Declaration;
  11079. Result:=DeclEl;
  11080. exit;
  11081. end;
  11082. El:=GetPasPropertyAncestor(El);
  11083. end;
  11084. end;
  11085. function TPasResolver.GetPasPropertySetter(El: TPasProperty): TPasElement;
  11086. // search the member variable or setter procedure of a property
  11087. var
  11088. DeclEl: TPasElement;
  11089. begin
  11090. Result:=nil;
  11091. while El<>nil do
  11092. begin
  11093. if El.WriteAccessor<>nil then
  11094. begin
  11095. DeclEl:=(El.WriteAccessor.CustomData as TResolvedReference).Declaration;
  11096. Result:=DeclEl;
  11097. exit;
  11098. end;
  11099. El:=GetPasPropertyAncestor(El);
  11100. end;
  11101. end;
  11102. function TPasResolver.GetPasPropertyStored(El: TPasProperty): TPasElement;
  11103. // search the member variable or setter procedure of a property
  11104. var
  11105. DeclEl: TPasElement;
  11106. begin
  11107. Result:=nil;
  11108. while El<>nil do
  11109. begin
  11110. if El.StoredAccessor<>nil then
  11111. begin
  11112. DeclEl:=(El.StoredAccessor.CustomData as TResolvedReference).Declaration;
  11113. Result:=DeclEl;
  11114. exit;
  11115. end;
  11116. El:=GetPasPropertyAncestor(El);
  11117. end;
  11118. end;
  11119. function TPasResolver.CheckParamCompatibility(Expr: TPasExpr;
  11120. Param: TPasArgument; ParamNo: integer; RaiseOnError: boolean;
  11121. SetReferenceFlags: boolean): integer;
  11122. var
  11123. ExprResolved, ParamResolved: TPasResolverResult;
  11124. NeedVar: Boolean;
  11125. RHSFlags: TPasResolverComputeFlags;
  11126. begin
  11127. Result:=cIncompatible;
  11128. NeedVar:=Param.Access in [argVar, argOut];
  11129. ComputeElement(Param,ParamResolved,[]);
  11130. {$IFDEF VerbosePasResolver}
  11131. writeln('TPasResolver.CheckParamCompatibility Param=',GetTreeDbg(Param,2),' ParamResolved=',GetResolverResultDbg(ParamResolved));
  11132. {$ENDIF}
  11133. if (ParamResolved.TypeEl=nil) and (Param.ArgType<>nil) then
  11134. RaiseInternalError(20160922163628,'GetResolvedType returned TypeEl=nil for '+GetTreeDbg(Param));
  11135. if (Expr is TParamsExpr) and (TParamsExpr(Expr).Kind=pekSet) then
  11136. begin
  11137. // passing a const set
  11138. if NeedVar then
  11139. begin
  11140. if RaiseOnError then
  11141. RaiseMsg(20170216152450,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Expr);
  11142. exit;
  11143. end;
  11144. if ParamResolved.TypeEl is TPasArrayType then
  11145. begin
  11146. Result:=CheckConstArrayCompatibility(TParamsExpr(Expr),ParamResolved,
  11147. RaiseOnError,[],Expr);
  11148. if (Result=cIncompatible) and RaiseOnError then
  11149. RaiseInternalError(20170326211129);
  11150. exit;
  11151. end;
  11152. end;
  11153. RHSFlags:=[];
  11154. if NeedVar then
  11155. Include(RHSFlags,rcNoImplicitProc)
  11156. else if IsProcedureType(ParamResolved,true)
  11157. or (ParamResolved.BaseType=btPointer)
  11158. or (Param.ArgType=nil) then
  11159. Include(RHSFlags,rcNoImplicitProcType);
  11160. if SetReferenceFlags then
  11161. Include(RHSFlags,rcSetReferenceFlags);
  11162. ComputeElement(Expr,ExprResolved,RHSFlags);
  11163. {$IFDEF VerbosePasResolver}
  11164. writeln('TPasResolver.CheckParamCompatibility Expr=',GetTreeDbg(Expr,2),' ResolvedExpr=',GetResolverResultDbg(ExprResolved),' RHSFlags=',dbgs(RHSFlags));
  11165. {$ENDIF}
  11166. if NeedVar then
  11167. begin
  11168. // Expr must be a variable
  11169. if not ResolvedElCanBeVarParam(ExprResolved) then
  11170. begin
  11171. {$IFDEF VerbosePasResolver}
  11172. writeln('TPasResolver.CheckParamCompatibility NeedWritable: ',GetResolverResultDbg(ExprResolved));
  11173. {$ENDIF}
  11174. if RaiseOnError then
  11175. RaiseMsg(20170216152450,nVariableIdentifierExpected,sVariableIdentifierExpected,[],Expr);
  11176. exit;
  11177. end;
  11178. if (ParamResolved.BaseType=ExprResolved.BaseType) then
  11179. begin
  11180. if IsSameType(ParamResolved.TypeEl,ExprResolved.TypeEl) then
  11181. exit(cExact);
  11182. end;
  11183. if (Param.ArgType=nil) then
  11184. exit(cExact); // untyped argument
  11185. if RaiseOnError then
  11186. RaiseIncompatibleType(20170216152452,nIncompatibleTypeArgNoVarParamMustMatchExactly,
  11187. [IntToStr(ParamNo+1)],ExprResolved.TypeEl,ParamResolved.TypeEl,
  11188. Expr);
  11189. exit(cIncompatible);
  11190. end;
  11191. Result:=CheckAssignResCompatibility(ParamResolved,ExprResolved,Expr,false);
  11192. if (Result=cIncompatible) and RaiseOnError then
  11193. RaiseIncompatibleTypeRes(20170216152454,nIncompatibleTypeArgNo,
  11194. [IntToStr(ParamNo+1)],ExprResolved,ParamResolved,Expr);
  11195. end;
  11196. function TPasResolver.CheckAssignCompatibilityUserType(const LHS,
  11197. RHS: TPasResolverResult; ErrorEl: TPasElement; RaiseOnIncompatible: boolean
  11198. ): integer;
  11199. var
  11200. RTypeEl, LTypeEl: TPasType;
  11201. SrcResolved, DstResolved: TPasResolverResult;
  11202. LArray, RArray: TPasArrayType;
  11203. function RaiseIncompatType: integer;
  11204. begin
  11205. if not RaiseOnIncompatible then exit(cIncompatible);
  11206. RaiseIncompatibleTypeRes(20170216152505,nIncompatibleTypesGotExpected,
  11207. [],RHS,LHS,ErrorEl);
  11208. end;
  11209. begin
  11210. if (RHS.TypeEl=nil) then
  11211. RaiseInternalError(20160922163645);
  11212. if (LHS.TypeEl=nil) then
  11213. RaiseInternalError(20160922163648);
  11214. LTypeEl:=LHS.TypeEl;
  11215. RTypeEl:=RHS.TypeEl;
  11216. if LTypeEl=RTypeEl then
  11217. exit(cExact);
  11218. {$IFDEF VerbosePasResolver}
  11219. writeln('TPasResolver.CheckAssignCompatibilityUserType LTypeEl=',GetObjName(LTypeEl),' RTypeEl=',GetObjName(RTypeEl));
  11220. {$ENDIF}
  11221. Result:=-1;
  11222. if LTypeEl.ClassType=TPasClassType then
  11223. begin
  11224. if RHS.BaseType=btNil then
  11225. Result:=cExact
  11226. else if RTypeEl.ClassType=TPasClassType then
  11227. begin
  11228. Result:=CheckSrcIsADstType(RHS,LHS,ErrorEl);
  11229. if (Result=cIncompatible) and RaiseOnIncompatible then
  11230. RaiseIncompatibleType(20170216152458,nIncompatibleTypesGotExpected,
  11231. [],RTypeEl,LTypeEl,ErrorEl);
  11232. end
  11233. else
  11234. exit(RaiseIncompatType);
  11235. end
  11236. else if LTypeEl.ClassType=TPasClassOfType then
  11237. begin
  11238. if RHS.BaseType=btNil then
  11239. Result:=cExact
  11240. else if (RTypeEl.ClassType=TPasClassOfType) then
  11241. begin
  11242. // e.g. ImageClass:=AnotherImageClass;
  11243. Result:=CheckClassIsClass(TPasClassOfType(RTypeEl).DestType,
  11244. TPasClassOfType(LTypeEl).DestType,ErrorEl);
  11245. if (Result=cIncompatible) and RaiseOnIncompatible then
  11246. RaiseMsg(20170216152500,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  11247. ['class of '+TPasClassOfType(RTypeEl).DestType.FullName,'class of '+TPasClassOfType(LTypeEl).DestType.FullName],ErrorEl);
  11248. end
  11249. else if (RHS.IdentEl is TPasClassType) then
  11250. begin
  11251. // e.g. ImageClass:=TFPMemoryImage;
  11252. Result:=CheckClassIsClass(RTypeEl,TPasClassOfType(LTypeEl).DestType,ErrorEl);
  11253. if (Result=cIncompatible) and RaiseOnIncompatible then
  11254. RaiseMsg(20170216152501,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  11255. [RTypeEl.Name,'class of '+TPasClassOfType(LTypeEl).DestType.FullName],ErrorEl);
  11256. // do not check rrfReadable -> exit
  11257. exit;
  11258. end;
  11259. end
  11260. else if LTypeEl is TPasProcedureType then
  11261. begin
  11262. if RHS.BaseType=btNil then
  11263. exit(cExact);
  11264. //writeln('TPasResolver.CheckAssignCompatibilityUserType LTypeEl=',GetObjName(LTypeEl),' RHS.BaseType=',BaseTypeNames[RHS.BaseType],' RTypeEl=',GetObjName(RTypeEl),' RHS.IdentEl=',GetObjName(RHS.IdentEl),' RHS.ExprEl=',GetObjName(RHS.ExprEl),' rrfReadable=',rrfReadable in RHS.Flags);
  11265. if (LTypeEl.ClassType=RTypeEl.ClassType)
  11266. and (rrfReadable in RHS.Flags) then
  11267. begin
  11268. // e.g. ProcVar1:=ProcVar2
  11269. if CheckProcTypeCompatibility(TPasProcedureType(LTypeEl),TPasProcedureType(RTypeEl),
  11270. true,ErrorEl,RaiseOnIncompatible) then
  11271. exit(cExact);
  11272. end;
  11273. if RaiseOnIncompatible then
  11274. begin
  11275. if (RTypeEl is TPasProcedureType) and (rrfReadable in RHS.Flags) then
  11276. RaiseMsg(20170404154738,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  11277. [RTypeEl.ElementTypeName,LTypeEl.ElementTypeName],ErrorEl);
  11278. end;
  11279. end
  11280. else if LTypeEl.ClassType=TPasArrayType then
  11281. begin
  11282. // arrays of different types
  11283. if IsOpenArray(LTypeEl) and (RTypeEl.ClassType=TPasArrayType) then
  11284. begin
  11285. LArray:=TPasArrayType(LTypeEl);
  11286. RArray:=TPasArrayType(RTypeEl);
  11287. if length(LArray.Ranges)=length(RArray.Ranges) then
  11288. begin
  11289. if CheckProcArgTypeCompatibility(LArray.ElType,RArray.ElType) then
  11290. Result:=cExact
  11291. else if RaiseOnIncompatible then
  11292. RaiseMsg(20170328110050,nIncompatibleTypesGotExpected,sIncompatibleTypesGotExpected,
  11293. ['array of '+LArray.ElType.FullName,
  11294. 'array of '+RArray.ElType.FullName],ErrorEl)
  11295. else
  11296. exit(cIncompatible);
  11297. end;
  11298. end;
  11299. end
  11300. else if RTypeEl.ClassType=TPasEnumType then
  11301. begin
  11302. // enums of different type
  11303. end
  11304. else if RTypeEl.ClassType=TPasSetType then
  11305. begin
  11306. // sets of different type are compatible if enum types are compatible
  11307. if LTypeEl.ClassType=TPasSetType then
  11308. begin
  11309. ComputeElement(TPasSetType(LTypeEl).EnumType,DstResolved,[]);
  11310. ComputeElement(TPasSetType(RTypeEl).EnumType,SrcResolved,[]);
  11311. if (SrcResolved.TypeEl<>nil)
  11312. and (SrcResolved.TypeEl=DstResolved.TypeEl) then
  11313. Result:=cExact
  11314. else if (SrcResolved.TypeEl.CustomData is TResElDataBaseType)
  11315. and (DstResolved.TypeEl.CustomData is TResElDataBaseType)
  11316. and (CompareText(SrcResolved.TypeEl.Name,DstResolved.TypeEl.Name)=0) then
  11317. Result:=cExact
  11318. else if RaiseOnIncompatible then
  11319. RaiseIncompatibleTypeRes(20170216152510,nIncompatibleTypesGotExpected,
  11320. [],SrcResolved,DstResolved,ErrorEl)
  11321. else
  11322. exit(cIncompatible);
  11323. end
  11324. else
  11325. exit(RaiseIncompatType);
  11326. end
  11327. else
  11328. RaiseNotYetImplemented(20160922163654,ErrorEl);
  11329. if Result=-1 then
  11330. exit(RaiseIncompatType);
  11331. if not (rrfReadable in RHS.Flags) then
  11332. exit(RaiseIncompatType);
  11333. end;
  11334. function TPasResolver.CheckAssignCompatibilityArrayType(const LHS,
  11335. RHS: TPasResolverResult; ErrorEl: TPasElement; RaiseOnIncompatible: boolean
  11336. ): integer;
  11337. procedure CheckRange(ArrType: TPasArrayType; RangeIndex: integer;
  11338. Values: TPasResolverResult; ErrorEl: TPasElement);
  11339. var
  11340. Range, Value, Expr: TPasExpr;
  11341. RangeResolved, ValueResolved, ElTypeResolved: TPasResolverResult;
  11342. i, Count: Integer;
  11343. IsLastRange: Boolean;
  11344. ArrayValues: TPasExprArray;
  11345. begin
  11346. if length(ArrType.Ranges)=0 then
  11347. begin
  11348. if (Values.ExprEl<>nil) then
  11349. begin
  11350. Expr:=Values.ExprEl;
  11351. if Expr.ClassType=TArrayValues then
  11352. Count:=length(TArrayValues(Expr).Values)
  11353. else if (Expr.ClassType=TParamsExpr) and (TParamsExpr(Expr).Kind=pekSet) then
  11354. Count:=length(TParamsExpr(Expr).Params)
  11355. else if (Values.BaseType in btAllStringAndChars) and IsVarInit(Expr) then
  11356. begin
  11357. // const a: dynarray = string
  11358. ComputeElement(ArrType.ElType,ElTypeResolved,[rcType]);
  11359. if ElTypeResolved.BaseType in btAllChars then
  11360. Result:=cExact;
  11361. exit;
  11362. end
  11363. else
  11364. begin
  11365. // single value
  11366. exit;
  11367. end;
  11368. end;
  11369. IsLastRange:=true;
  11370. end
  11371. else
  11372. begin
  11373. Range:=ArrType.Ranges[RangeIndex];
  11374. ComputeElement(Range,RangeResolved,[rcConstant]);
  11375. Count:=GetRangeLength(RangeResolved);
  11376. if Count=0 then
  11377. RaiseNotYetImplemented(20170222232409,Values.ExprEl,'range '+GetResolverResultDbg(RangeResolved));
  11378. IsLastRange:=RangeIndex+1=length(ArrType.Ranges);
  11379. end;
  11380. if IsLastRange then
  11381. begin
  11382. ComputeElement(ArrType.ElType,ElTypeResolved,[rcType]);
  11383. ElTypeResolved.ExprEl:=Range;
  11384. Include(ElTypeResolved.Flags,rrfWritable);
  11385. end
  11386. else
  11387. ElTypeResolved.BaseType:=btNone;
  11388. if (Values.ExprEl<>nil) and (Values.ExprEl.ClassType=TArrayValues) then
  11389. begin
  11390. ArrayValues:=TArrayValues(Values.ExprEl).Values;
  11391. // check each value
  11392. for i:=0 to Count-1 do
  11393. begin
  11394. if i=length(ArrayValues) then
  11395. begin
  11396. // not enough values
  11397. if length(ArrayValues)>0 then
  11398. ErrorEl:=ArrayValues[length(ArrayValues)-1];
  11399. RaiseMsg(20170222233001,nExpectXArrayElementsButFoundY,sExpectXArrayElementsButFoundY,
  11400. [IntToStr(Count),IntToStr(length(ArrayValues))],ErrorEl);
  11401. end;
  11402. Value:=ArrayValues[i];
  11403. ComputeElement(Value,ValueResolved,[rcConstant]);
  11404. if IsLastRange then
  11405. begin
  11406. // last dimension -> check element type
  11407. Result:=CheckAssignResCompatibility(ElTypeResolved,ValueResolved,Value,RaiseOnIncompatible);
  11408. if Result=cIncompatible then
  11409. exit;
  11410. end
  11411. else
  11412. begin
  11413. // multi dimensional array -> check next range
  11414. CheckRange(ArrType,RangeIndex+1,ValueResolved,Value);
  11415. end;
  11416. end;
  11417. if Count<length(ArrayValues) then
  11418. begin
  11419. // too many values
  11420. ErrorEl:=ArrayValues[Count];
  11421. if RaiseOnIncompatible then
  11422. RaiseMsg(20170222233605,nExpectXArrayElementsButFoundY,sExpectXArrayElementsButFoundY,
  11423. [IntToStr(Count),IntToStr(length(ArrayValues))],ErrorEl);
  11424. exit;
  11425. end;
  11426. end
  11427. else
  11428. begin
  11429. // single value
  11430. // Note: the parser does not store the difference between (1) and 1
  11431. if (not IsLastRange) or (Count>1) then
  11432. begin
  11433. if RaiseOnIncompatible then
  11434. RaiseMsg(20170223095307,nExpectXArrayElementsButFoundY,sExpectXArrayElementsButFoundY,
  11435. [IntToStr(Count),'1'],ErrorEl);
  11436. exit;
  11437. end;
  11438. // check element type
  11439. Result:=CheckAssignResCompatibility(ElTypeResolved,Values,ErrorEl,RaiseOnIncompatible);
  11440. if Result=cIncompatible then
  11441. exit;
  11442. end;
  11443. end;
  11444. var
  11445. LArrType: TPasArrayType;
  11446. begin
  11447. Result:=cIncompatible;
  11448. {$IFDEF VerbosePasResolver}
  11449. writeln('TPasResolver.CheckAssignCompatibilityArrayType LHS=',GetResolverResultDbg(LHS),' RHS=',GetResolverResultDbg(RHS));
  11450. {$ENDIF}
  11451. if (LHS.BaseType<>btContext) or (not (LHS.TypeEl is TPasArrayType)) then
  11452. RaiseInternalError(20170222230012);
  11453. if not (rrfReadable in RHS.Flags) then
  11454. exit;
  11455. LArrType:=TPasArrayType(LHS.TypeEl);
  11456. if RHS.ExprEl=nil then
  11457. exit;
  11458. if IsEmptySet(RHS) then
  11459. begin
  11460. if length(LArrType.Ranges)=0 then
  11461. exit(cExact); // empty set fits dyn and open array
  11462. end;
  11463. CheckRange(LArrType,0,RHS,ErrorEl);
  11464. end;
  11465. function TPasResolver.CheckConstArrayCompatibility(Params: TParamsExpr;
  11466. const ArrayResolved: TPasResolverResult; RaiseOnError: boolean;
  11467. Flags: TPasResolverComputeFlags; StartEl: TPasElement): integer;
  11468. // check that each Param fits the array element type
  11469. var
  11470. i, ParamComp: Integer;
  11471. Param: TPasExpr;
  11472. ArrayType: TPasArrayType;
  11473. ElTypeResolved, ParamResolved: TPasResolverResult;
  11474. ElTypeIsArray: boolean;
  11475. begin
  11476. {$IFDEF VerbosePasResolver}
  11477. writeln('TPasResolver.CheckConstArrayCompatibility Params.length=',length(Params.Params),
  11478. ' ArrayResolved=',GetResolverResultDbg(ArrayResolved),' Flags=',dbgs(Flags));
  11479. {$ENDIF}
  11480. if not (ArrayResolved.TypeEl is TPasArrayType) then
  11481. RaiseInternalError(20170326204957);
  11482. ArrayType:=TPasArrayType(ArrayResolved.TypeEl);
  11483. ComputeElement(ArrayType.ElType,ElTypeResolved,Flags+[rcType]);
  11484. ElTypeIsArray:=ResolveAliasType(ElTypeResolved.TypeEl) is TPasArrayType;
  11485. Result:=cExact;
  11486. for i:=0 to length(Params.Params)-1 do
  11487. begin
  11488. Param:=Params.Params[i];
  11489. if ElTypeIsArray and (Param is TParamsExpr) and (TParamsExpr(Param).Kind=pekSet) then
  11490. ParamComp:=CheckConstArrayCompatibility(TParamsExpr(Param),ElTypeResolved,
  11491. RaiseOnError,Flags,StartEl)
  11492. else
  11493. begin
  11494. ComputeElement(Param,ParamResolved,Flags,StartEl);
  11495. ParamComp:=CheckAssignResCompatibility(ElTypeResolved,ParamResolved,Param,RaiseOnError);
  11496. end;
  11497. if ParamComp=cIncompatible then
  11498. exit(cIncompatible);
  11499. inc(Result,ParamComp);
  11500. end;
  11501. end;
  11502. function TPasResolver.CheckEqualCompatibilityUserType(const TypeA,
  11503. TypeB: TPasResolverResult; ErrorEl: TPasElement; RaiseOnIncompatible: boolean
  11504. ): integer;
  11505. var
  11506. ElA, ElB: TPasType;
  11507. AResolved, BResolved: TPasResolverResult;
  11508. function IncompatibleElements: integer;
  11509. begin
  11510. Result:=cIncompatible;
  11511. if not RaiseOnIncompatible then exit;
  11512. RaiseIncompatibleType(20170216152513,nIncompatibleTypesGotExpected,
  11513. [],ElA,ElB,ErrorEl);
  11514. end;
  11515. begin
  11516. if (TypeA.TypeEl=nil) then
  11517. RaiseInternalError(20161007223118);
  11518. if (TypeB.TypeEl=nil) then
  11519. RaiseInternalError(20161007223119);
  11520. ElA:=TypeA.TypeEl;
  11521. ElB:=TypeB.TypeEl;
  11522. if ElA=ElB then
  11523. exit(cExact);
  11524. if ElA.ClassType=TPasClassType then
  11525. begin
  11526. if TypeA.IdentEl is TPasType then
  11527. begin
  11528. if (TypeB.IdentEl is TPasType) and (ElA=ElB) then
  11529. // e.g. if TFPMemoryImage=TFPMemoryImage then ;
  11530. exit(cExact);
  11531. if ElB.ClassType=TPasClassOfType then
  11532. begin
  11533. // e.g. if TFPMemoryImage=ImageClass then ;
  11534. Result:=CheckClassIsClass(ElA,TPasClassOfType(ElB).DestType,ErrorEl);
  11535. if (Result=cIncompatible) and RaiseOnIncompatible then
  11536. RaiseMsg(20170216152515,nTypesAreNotRelated,sTypesAreNotRelated,[],ErrorEl);
  11537. exit;
  11538. end;
  11539. end
  11540. else if ElB.ClassType=TPasClassType then
  11541. begin
  11542. // e.g. if Sender=Button1 then
  11543. Result:=CheckSrcIsADstType(TypeA,TypeB,ErrorEl);
  11544. if Result=cIncompatible then
  11545. Result:=CheckSrcIsADstType(TypeB,TypeA,ErrorEl);
  11546. if (Result=cIncompatible) and RaiseOnIncompatible then
  11547. RaiseMsg(20170216152517,nTypesAreNotRelated,sTypesAreNotRelated,[],ErrorEl);
  11548. exit;
  11549. end;
  11550. exit(IncompatibleElements);
  11551. end
  11552. else if ElA.ClassType=TPasClassOfType then
  11553. begin
  11554. if ElB.ClassType=TPasClassOfType then
  11555. begin
  11556. // for example: if ImageClass=ImageClass then
  11557. Result:=CheckClassIsClass(TPasClassOfType(ElA).DestType,
  11558. TPasClassOfType(ElB).DestType,ErrorEl);
  11559. if Result=cIncompatible then
  11560. Result:=CheckClassIsClass(TPasClassOfType(ElB).DestType,
  11561. TPasClassOfType(ElA).DestType,ErrorEl);
  11562. if (Result=cIncompatible) and RaiseOnIncompatible then
  11563. RaiseMsg(20170216152519,nTypesAreNotRelated,sTypesAreNotRelated,[],ErrorEl);
  11564. exit;
  11565. end
  11566. else if TypeB.IdentEl is TPasClassType then
  11567. begin
  11568. // for example: if ImageClass=TFPMemoryImage then
  11569. Result:=CheckClassIsClass(TPasClassType(TypeB.IdentEl),TPasClassOfType(ElA).DestType,ErrorEl);
  11570. if (Result=cIncompatible) and RaiseOnIncompatible then
  11571. RaiseMsg(20170216152520,nTypesAreNotRelated,sTypesAreNotRelated,[],ErrorEl);
  11572. exit;
  11573. end;
  11574. exit(IncompatibleElements);
  11575. end
  11576. else if ElA.ClassType=TPasEnumType then
  11577. begin
  11578. // enums of different type
  11579. if not RaiseOnIncompatible then
  11580. exit(cIncompatible);
  11581. if ElB.ClassType=TPasEnumValue then
  11582. RaiseIncompatibleType(20170216152523,nIncompatibleTypesGotExpected,
  11583. [],TPasEnumType(ElA),TPasEnumType(ElB),ErrorEl)
  11584. else
  11585. exit(IncompatibleElements);
  11586. end
  11587. else if ElA.ClassType=TPasSetType then
  11588. begin
  11589. if ElB.ClassType=TPasSetType then
  11590. begin
  11591. ComputeElement(TPasSetType(ElA).EnumType,AResolved,[]);
  11592. ComputeElement(TPasSetType(ElB).EnumType,BResolved,[]);
  11593. if (AResolved.TypeEl<>nil)
  11594. and (AResolved.TypeEl=BResolved.TypeEl) then
  11595. exit(cExact);
  11596. if (AResolved.TypeEl.CustomData is TResElDataBaseType)
  11597. and (BResolved.TypeEl.CustomData is TResElDataBaseType)
  11598. and (CompareText(AResolved.TypeEl.Name,BResolved.TypeEl.Name)=0) then
  11599. exit(cExact);
  11600. if RaiseOnIncompatible then
  11601. RaiseIncompatibleTypeRes(20170216152524,nIncompatibleTypesGotExpected,
  11602. [],AResolved,BResolved,ErrorEl)
  11603. else
  11604. exit(cIncompatible);
  11605. end
  11606. else
  11607. exit(IncompatibleElements);
  11608. end
  11609. else if (ElA is TPasProcedureType) and (rrfReadable in TypeA.Flags) then
  11610. begin
  11611. if (ElB is TPasProcedureType) and (rrfReadable in TypeB.Flags) then
  11612. begin
  11613. // e.g. ProcVar1 = ProcVar2
  11614. if CheckProcTypeCompatibility(TPasProcedureType(ElA),TPasProcedureType(ElB),
  11615. false,nil,false) then
  11616. exit(cExact);
  11617. end
  11618. else
  11619. exit(IncompatibleElements);
  11620. end;
  11621. exit(IncompatibleElements);
  11622. end;
  11623. function TPasResolver.CheckTypeCast(El: TPasType; Params: TParamsExpr;
  11624. RaiseOnError: boolean): integer;
  11625. // for example if TClassA(AnObject)=nil then ;
  11626. var
  11627. Param: TPasExpr;
  11628. ParamResolved, ResolvedEl: TPasResolverResult;
  11629. begin
  11630. if length(Params.Params)<>1 then
  11631. begin
  11632. if RaiseOnError then
  11633. RaiseMsg(20170216152526,nWrongNumberOfParametersForTypeCast,
  11634. sWrongNumberOfParametersForTypeCast,[El.Name],Params);
  11635. exit(cIncompatible);
  11636. end;
  11637. Param:=Params.Params[0];
  11638. ComputeElement(Param,ParamResolved,[rcNoImplicitProcType]);
  11639. ComputeElement(El,ResolvedEl,[rcType]);
  11640. Result:=CheckTypeCastRes(ParamResolved,ResolvedEl,Param,RaiseOnError);
  11641. end;
  11642. function TPasResolver.CheckTypeCastRes(const FromResolved,
  11643. ToResolved: TPasResolverResult; ErrorEl: TPasElement; RaiseOnError: boolean
  11644. ): integer;
  11645. var
  11646. ToTypeEl, ToClassType, FromClassType: TPasType;
  11647. ToTypeBaseType: TResolverBaseType;
  11648. C: TClass;
  11649. ToProcType, FromProcType: TPasProcedureType;
  11650. begin
  11651. Result:=cIncompatible;
  11652. ToTypeEl:=ResolveAliasType(ToResolved.TypeEl);
  11653. if (ToTypeEl<>nil)
  11654. and (rrfReadable in FromResolved.Flags) then
  11655. begin
  11656. C:=ToTypeEl.ClassType;
  11657. if FromResolved.BaseType=btUntyped then
  11658. begin
  11659. // typecast an untyped parameter
  11660. Result:=cCompatible;
  11661. end
  11662. else if C=TPasUnresolvedSymbolRef then
  11663. begin
  11664. if ToTypeEl.CustomData is TResElDataBaseType then
  11665. begin
  11666. // base type cast, e.g. double(aninteger)
  11667. if ToTypeEl=FromResolved.TypeEl then
  11668. exit(cExact);
  11669. ToTypeBaseType:=(ToTypeEl.CustomData as TResElDataBaseType).BaseType;
  11670. if ToTypeBaseType=FromResolved.BaseType then
  11671. Result:=cExact
  11672. else if ToTypeBaseType in btAllInteger then
  11673. begin
  11674. if FromResolved.BaseType in btAllInteger then
  11675. Result:=cCompatible
  11676. else if FromResolved.BaseType in btAllBooleans then
  11677. Result:=cCompatible;
  11678. end
  11679. else if ToTypeBaseType in btAllFloats then
  11680. begin
  11681. if FromResolved.BaseType in btAllFloats then
  11682. Result:=cCompatible
  11683. else if FromResolved.BaseType in btAllInteger then
  11684. Result:=cCompatible;
  11685. end
  11686. else if ToTypeBaseType in btAllBooleans then
  11687. begin
  11688. if FromResolved.BaseType in btAllBooleans then
  11689. Result:=cCompatible
  11690. else if FromResolved.BaseType in btAllInteger then
  11691. Result:=cCompatible;
  11692. end
  11693. else if ToTypeBaseType in btAllStrings then
  11694. begin
  11695. if FromResolved.BaseType in btAllStringAndChars then
  11696. Result:=cCompatible;
  11697. end
  11698. else if ToTypeBaseType=btPointer then
  11699. begin
  11700. if FromResolved.BaseType=btPointer then
  11701. Result:=cExact
  11702. else if FromResolved.BaseType=btContext then
  11703. begin
  11704. C:=FromResolved.TypeEl.ClassType;
  11705. if (C=TPasClassType)
  11706. or (C=TPasClassOfType)
  11707. or (C=TPasPointerType)
  11708. or ((C=TPasArrayType) and IsDynArray(FromResolved.TypeEl)) then
  11709. Result:=cExact
  11710. else if (C=TPasProcedureType) or (C=TPasFunctionType) then
  11711. begin
  11712. // from procvar to pointer
  11713. FromProcType:=TPasProcedureType(FromResolved.TypeEl);
  11714. if FromProcType.IsOfObject then
  11715. begin
  11716. if proMethodAddrAsPointer in Options then
  11717. Result:=cCompatible
  11718. else if RaiseOnError then
  11719. RaiseMsg(20170416183615,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11720. [FromProcType.ElementTypeName+' '+ProcTypeModifiers[ptmOfObject],
  11721. BaseTypeNames[btPointer]],ErrorEl);
  11722. end
  11723. else if FromProcType.IsNested then
  11724. begin
  11725. if RaiseOnError then
  11726. RaiseMsg(20170416183800,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11727. [FromProcType.ElementTypeName+' '+ProcTypeModifiers[ptmIsNested],
  11728. BaseTypeNames[btPointer]],ErrorEl);
  11729. end
  11730. else if FromProcType.IsReferenceTo then
  11731. begin
  11732. if proProcTypeWithoutIsNested in Options then
  11733. Result:=cCompatible
  11734. else if RaiseOnError then
  11735. RaiseMsg(20170419144311,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11736. [FromProcType.ElementTypeName+' '+ProcTypeModifiers[ptmReferenceTo],
  11737. BaseTypeNames[btPointer]],ErrorEl);
  11738. end
  11739. else
  11740. Result:=cCompatible;
  11741. end;
  11742. end;
  11743. end;
  11744. end;
  11745. end
  11746. else if C=TPasClassType then
  11747. begin
  11748. // to class
  11749. if FromResolved.BaseType=btContext then
  11750. begin
  11751. if FromResolved.TypeEl.ClassType=TPasClassType then
  11752. begin
  11753. if FromResolved.IdentEl is TPasType then
  11754. RaiseMsg(20170404162606,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl);
  11755. // type cast upwards or downwards
  11756. Result:=CheckSrcIsADstType(FromResolved,ToResolved,ErrorEl);
  11757. if Result=cIncompatible then
  11758. Result:=CheckSrcIsADstType(ToResolved,FromResolved,ErrorEl);
  11759. if Result=cIncompatible then
  11760. Result:=CheckTypeCastClassInstanceToClass(FromResolved,ToResolved,ErrorEl);
  11761. end
  11762. end
  11763. else if FromResolved.BaseType=btPointer then
  11764. begin
  11765. if IsBaseType(FromResolved.TypeEl,btPointer) then
  11766. Result:=cExact; // untyped pointer to class instance
  11767. end;
  11768. end
  11769. else if C=TPasClassOfType then
  11770. begin
  11771. //writeln('TPasResolver.CheckTypeCast class-of FromRes.TypeEl=',GetObjName(FromResolved.TypeEl),' FromRes.IdentEl=',GetObjName(FromResolved.IdentEl));
  11772. if FromResolved.BaseType=btContext then
  11773. begin
  11774. if FromResolved.TypeEl.ClassType=TPasClassOfType then
  11775. begin
  11776. if (FromResolved.IdentEl is TPasType) then
  11777. RaiseMsg(20170404162604,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl);
  11778. // type cast classof(classof-var) upwards or downwards
  11779. ToClassType:=TPasClassOfType(ToTypeEl).DestType;
  11780. FromClassType:=TPasClassOfType(FromResolved.TypeEl).DestType;
  11781. Result:=CheckClassesAreRelated(ToClassType,FromClassType,ErrorEl);
  11782. end;
  11783. end
  11784. else if FromResolved.BaseType=btPointer then
  11785. begin
  11786. if IsBaseType(FromResolved.TypeEl,btPointer) then
  11787. Result:=cExact; // untyped pointer to class-of
  11788. end;
  11789. end
  11790. else if C=TPasRecordType then
  11791. begin
  11792. if FromResolved.BaseType=btContext then
  11793. begin
  11794. if FromResolved.TypeEl.ClassType=TPasRecordType then
  11795. begin
  11796. // typecast record to record
  11797. Result:=cExact;
  11798. end;
  11799. end;
  11800. end
  11801. else if C=TPasEnumType then
  11802. begin
  11803. if CheckIsOrdinal(FromResolved,ErrorEl,true) then
  11804. Result:=cExact;
  11805. end
  11806. else if C=TPasArrayType then
  11807. begin
  11808. if FromResolved.BaseType=btContext then
  11809. begin
  11810. if FromResolved.TypeEl.ClassType=TPasArrayType then
  11811. Result:=CheckTypeCastArray(TPasArrayType(FromResolved.TypeEl),
  11812. TPasArrayType(ToTypeEl),ErrorEl,RaiseOnError);
  11813. end
  11814. else if FromResolved.BaseType=btPointer then
  11815. begin
  11816. if IsDynArray(ToResolved.TypeEl)
  11817. and IsBaseType(FromResolved.TypeEl,btPointer) then
  11818. Result:=cExact; // untyped pointer to dynnamic array
  11819. end;
  11820. end
  11821. else if (C=TPasProcedureType) or (C=TPasFunctionType) then
  11822. begin
  11823. ToProcType:=TPasProcedureType(ToTypeEl);
  11824. if IsBaseType(FromResolved.TypeEl,btPointer) then
  11825. begin
  11826. // type cast untyped pointer value to proctype
  11827. if ToProcType.IsOfObject then
  11828. begin
  11829. if proMethodAddrAsPointer in Options then
  11830. Result:=cCompatible
  11831. else if RaiseOnError then
  11832. RaiseMsg(20170416183940,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11833. [BaseTypeNames[btPointer],
  11834. ToProcType.ElementTypeName+' '+ProcTypeModifiers[ptmOfObject]],ErrorEl);
  11835. end
  11836. else if ToProcType.IsNested then
  11837. begin
  11838. if RaiseOnError then
  11839. RaiseMsg(20170416184149,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11840. [BaseTypeNames[btPointer],
  11841. ToProcType.ElementTypeName+' '+ProcTypeModifiers[ptmIsNested]],ErrorEl);
  11842. end
  11843. else if ToProcType.IsReferenceTo then
  11844. begin
  11845. if proMethodAddrAsPointer in Options then
  11846. Result:=cCompatible
  11847. else if RaiseOnError then
  11848. RaiseMsg(20170419144357,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11849. [BaseTypeNames[btPointer],
  11850. ToProcType.ElementTypeName+' '+ProcTypeModifiers[ptmReferenceTo]],ErrorEl);
  11851. end
  11852. else
  11853. Result:=cCompatible;
  11854. end
  11855. else if FromResolved.BaseType=btContext then
  11856. begin
  11857. if FromResolved.TypeEl is TPasProcedureType then
  11858. begin
  11859. // type cast procvar to proctype
  11860. FromProcType:=TPasProcedureType(FromResolved.TypeEl);
  11861. if ToProcType.IsReferenceTo then
  11862. Result:=cCompatible
  11863. else if FromProcType.IsReferenceTo then
  11864. Result:=cCompatible
  11865. else if (FromProcType.IsOfObject<>ToProcType.IsOfObject)
  11866. and not (proMethodAddrAsPointer in Options) then
  11867. begin
  11868. if RaiseOnError then
  11869. RaiseMsg(20170416183109,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11870. [FromProcType.ElementTypeName+BoolToStr(FromProcType.IsOfObject,' '+ProcTypeModifiers[ptmOfObject],''),
  11871. ToProcType.ElementTypeName+BoolToStr(ToProcType.IsOfObject,' '+ProcTypeModifiers[ptmOfObject],'')],ErrorEl);
  11872. end
  11873. else if FromProcType.IsNested<>ToProcType.IsNested then
  11874. begin
  11875. if RaiseOnError then
  11876. RaiseMsg(20170416183305,nIllegalTypeConversionTo,sIllegalTypeConversionTo,
  11877. [FromProcType.ElementTypeName+BoolToStr(FromProcType.IsNested,' '+ProcTypeModifiers[ptmIsNested],''),
  11878. ToProcType.ElementTypeName+BoolToStr(ToProcType.IsNested,' '+ProcTypeModifiers[ptmIsNested],'')],ErrorEl);
  11879. end
  11880. else
  11881. Result:=cCompatible;
  11882. end;
  11883. end;
  11884. end;
  11885. end
  11886. else if ToTypeEl<>nil then
  11887. begin
  11888. // FromResolved is not readable
  11889. if FromResolved.BaseType=btContext then
  11890. begin
  11891. if (FromResolved.TypeEl.ClassType=TPasClassType)
  11892. and (FromResolved.TypeEl=FromResolved.IdentEl)
  11893. and (ToResolved.BaseType=btContext)
  11894. and (ToResolved.TypeEl.ClassType=TPasClassOfType)
  11895. and (ToResolved.TypeEl=ToResolved.IdentEl) then
  11896. begin
  11897. // for example class-of(Self) in a class function
  11898. ToClassType:=TPasClassOfType(ToTypeEl).DestType;
  11899. FromClassType:=TPasClassType(FromResolved.TypeEl);
  11900. Result:=CheckClassesAreRelated(ToClassType,FromClassType,ErrorEl);
  11901. end;
  11902. end;
  11903. if (Result=cIncompatible) and RaiseOnError then
  11904. begin
  11905. if FromResolved.IdentEl is TPasType then
  11906. RaiseMsg(20170404162610,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl);
  11907. end;
  11908. end;
  11909. if Result=cIncompatible then
  11910. begin
  11911. {$IFDEF VerbosePasResolver}
  11912. writeln('TPasResolver.CheckTypeCastRes From={',GetResolverResultDbg(FromResolved),'} To={',GetResolverResultDbg(ToResolved),'}');
  11913. {$ENDIF}
  11914. if RaiseOnError then
  11915. RaiseIncompatibleTypeRes(20170216152528,nIllegalTypeConversionTo,
  11916. [],FromResolved,ToResolved,ErrorEl);
  11917. exit;
  11918. end;
  11919. end;
  11920. function TPasResolver.CheckTypeCastArray(FromType, ToType: TPasArrayType;
  11921. ErrorEl: TPasElement; RaiseOnError: boolean): integer;
  11922. function NextDim(var ArrType: TPasArrayType; var NextIndex: integer;
  11923. out ElTypeResolved: TPasResolverResult): boolean;
  11924. begin
  11925. inc(NextIndex);
  11926. if NextIndex<length(ArrType.Ranges) then
  11927. begin
  11928. ElTypeResolved.BaseType:=btNone;
  11929. exit(true);
  11930. end;
  11931. ComputeElement(ArrType.ElType,ElTypeResolved,[rcType]);
  11932. if (ElTypeResolved.BaseType<>btContext)
  11933. or (ElTypeResolved.TypeEl.ClassType<>TPasArrayType) then
  11934. exit(false);
  11935. ArrType:=TPasArrayType(ElTypeResolved.TypeEl);
  11936. NextIndex:=0;
  11937. Result:=true;
  11938. end;
  11939. var
  11940. FromIndex, ToIndex: Integer;
  11941. FromElTypeRes, ToElTypeRes: TPasResolverResult;
  11942. StartFromType, StartToType: TPasArrayType;
  11943. begin
  11944. {$IFDEF VerbosePasResolver}
  11945. writeln('TPasResolver.CheckTypeCastArray From=',GetTypeDescription(FromType),' ToType=',GetTypeDescription(ToType));
  11946. {$ENDIF}
  11947. StartFromType:=FromType;
  11948. StartToType:=ToType;
  11949. Result:=cIncompatible;
  11950. // check dimensions
  11951. FromIndex:=0;
  11952. ToIndex:=0;
  11953. repeat
  11954. {$IFDEF VerbosePasResolver}
  11955. writeln('TPasResolver.CheckTypeCastArray From=',GetTypeDescription(FromType),' FromIndex=',FromIndex,' ToType=',GetTypeDescription(ToType),' ToIndex=',ToIndex);
  11956. {$ENDIF}
  11957. if length(ToType.Ranges)=0 then
  11958. // ToType is dynamic/open array -> fits any size
  11959. else
  11960. begin
  11961. // ToType is ranged
  11962. // ToDo: check size of dimension
  11963. end;
  11964. // check next dimension
  11965. if not NextDim(FromType,FromIndex,FromElTypeRes) then
  11966. begin
  11967. // at end of FromType
  11968. if NextDim(ToType,ToIndex,ToElTypeRes) then
  11969. begin
  11970. {$IFDEF VerbosePasResolver}
  11971. writeln('TPasResolver.CheckTypeCastArray To has more dims than From: From=',GetTypeDescription(FromType),' FromIndex=',FromIndex,', ToType=',GetTypeDescription(ToType),' ToIndex=',ToIndex);
  11972. {$ENDIF}
  11973. break; // ToType has more dimensions
  11974. end;
  11975. // have same dimension -> check ElType
  11976. {$IFDEF VerbosePasResolver}
  11977. writeln('TPasResolver.CheckTypeCastArray check ElType From=',GetResolverResultDbg(FromElTypeRes),' To=',GetResolverResultDbg(ToElTypeRes));
  11978. {$ENDIF}
  11979. Include(FromElTypeRes.Flags,rrfReadable);
  11980. Result:=CheckTypeCastRes(FromElTypeRes,ToElTypeRes,ErrorEl,false);
  11981. break;
  11982. end
  11983. else
  11984. begin
  11985. // FromType has more dimensions
  11986. if not NextDim(ToType,ToIndex,ToElTypeRes) then
  11987. begin
  11988. {$IFDEF VerbosePasResolver}
  11989. writeln('TPasResolver.CheckTypeCastArray From has more dims than To: From=',GetTypeDescription(FromType),' FromIndex=',FromIndex,', ToType=',GetTypeDescription(ToType),' ToIndex=',ToIndex);
  11990. {$ENDIF}
  11991. break; // ToType has less dimensions
  11992. end;
  11993. end;
  11994. until false;
  11995. if (Result=cIncompatible) and RaiseOnError then
  11996. RaiseIncompatibleType(20170331124643,nIllegalTypeConversionTo,
  11997. [],StartFromType,StartToType,ErrorEl);
  11998. end;
  11999. procedure TPasResolver.ComputeElement(El: TPasElement; out
  12000. ResolvedEl: TPasResolverResult; Flags: TPasResolverComputeFlags;
  12001. StartEl: TPasElement);
  12002. procedure ComputeIdentifier(Expr: TPasExpr);
  12003. var
  12004. Ref: TResolvedReference;
  12005. Proc: TPasProcedure;
  12006. ProcType: TPasProcedureType;
  12007. aClass: TPasClassType;
  12008. begin
  12009. Ref:=TResolvedReference(Expr.CustomData);
  12010. ComputeElement(Ref.Declaration,ResolvedEl,Flags+[rcNoImplicitProc],StartEl);
  12011. if rrfConstInherited in Ref.Flags then
  12012. Exclude(ResolvedEl.Flags,rrfWritable);
  12013. {$IFDEF VerbosePasResolver}
  12014. if Expr is TPrimitiveExpr then
  12015. writeln('TPasResolver.ComputeElement.ComputeIdentifier TPrimitiveExpr "',TPrimitiveExpr(Expr).Value,'" ',GetResolverResultDbg(ResolvedEl),' Flags=',dbgs(Flags))
  12016. else
  12017. writeln('TPasResolver.ComputeElement.ComputeIdentifier "',GetObjName(Expr),'" ',GetResolverResultDbg(ResolvedEl),' Flags=',dbgs(Flags));
  12018. {$ENDIF}
  12019. if (ResolvedEl.BaseType=btProc) then
  12020. begin
  12021. if [rcNoImplicitProc,rcConstant,rcType]*Flags=[] then
  12022. begin
  12023. // a proc and implicit call without params is allowed -> check if possible
  12024. Proc:=ResolvedEl.IdentEl as TPasProcedure;
  12025. if not ProcNeedsParams(Proc.ProcType) then
  12026. begin
  12027. // parameter less proc -> implicit call
  12028. if ResolvedEl.IdentEl is TPasFunction then
  12029. begin
  12030. // function => return result
  12031. ComputeElement(TPasFunction(ResolvedEl.IdentEl).FuncType.ResultEl,
  12032. ResolvedEl,Flags+[rcType],StartEl);
  12033. Exclude(ResolvedEl.Flags,rrfWritable);
  12034. end
  12035. else if (ResolvedEl.IdentEl.ClassType=TPasConstructor)
  12036. and (rrfNewInstance in Ref.Flags) then
  12037. begin
  12038. // new instance constructor -> return value of type class
  12039. aClass:=GetReference_NewInstanceClass(Ref);
  12040. SetResolverValueExpr(ResolvedEl,btContext,aClass,TPrimitiveExpr(Expr),[rrfReadable]);
  12041. end
  12042. else if ParentNeedsExprResult(Expr) then
  12043. begin
  12044. // a procedure
  12045. exit;
  12046. end;
  12047. if rcSetReferenceFlags in Flags then
  12048. Include(Ref.Flags,rrfImplicitCallWithoutParams);
  12049. Include(ResolvedEl.Flags,rrfCanBeStatement);
  12050. end;
  12051. end;
  12052. end
  12053. else if IsProcedureType(ResolvedEl,true) then
  12054. begin
  12055. if [rcNoImplicitProc,rcNoImplicitProcType,rcConstant,rcType]*Flags=[] then
  12056. begin
  12057. // a proc type and implicit call without params is allowed -> check if possible
  12058. ProcType:=TPasProcedureType(ResolvedEl.TypeEl);
  12059. if not ProcNeedsParams(ProcType) then
  12060. begin
  12061. // parameter less proc -> implicit call
  12062. if ResolvedEl.TypeEl is TPasFunctionType then
  12063. // function => return result
  12064. ComputeElement(TPasFunctionType(ResolvedEl.TypeEl).ResultEl,
  12065. ResolvedEl,Flags+[rcType],StartEl)
  12066. else if ParentNeedsExprResult(Expr) then
  12067. begin
  12068. // a procedure has no result
  12069. exit;
  12070. end;
  12071. if rcSetReferenceFlags in Flags then
  12072. Include(Ref.Flags,rrfImplicitCallWithoutParams);
  12073. Include(ResolvedEl.Flags,rrfCanBeStatement);
  12074. end;
  12075. end;
  12076. end;
  12077. end;
  12078. var
  12079. DeclEl: TPasElement;
  12080. ElClass: TClass;
  12081. bt: TResolverBaseType;
  12082. begin
  12083. if StartEl=nil then StartEl:=El;
  12084. ResolvedEl:=Default(TPasResolverResult);
  12085. {$IFDEF VerbosePasResolver}
  12086. writeln('TPasResolver.ComputeElement El=',GetObjName(El),' SkipTypeAlias=',rcSkipTypeAlias in Flags);
  12087. {$ENDIF}
  12088. if El=nil then
  12089. exit;
  12090. ElClass:=El.ClassType;
  12091. if ElClass=TPrimitiveExpr then
  12092. begin
  12093. case TPrimitiveExpr(El).Kind of
  12094. pekIdent,pekSelf:
  12095. begin
  12096. if not (El.CustomData is TResolvedReference) then
  12097. RaiseNotYetImplemented(20160922163658,El,'Value="'+TPrimitiveExpr(El).Value+'" CustomData='+GetObjName(El.CustomData)+' '+GetElementSourcePosStr(El));
  12098. ComputeIdentifier(TPrimitiveExpr(El));
  12099. end;
  12100. pekNumber:
  12101. // ToDo: check if btByte, btSmallInt, btSingle, ...
  12102. if Pos('.',TPrimitiveExpr(El).Value)>0 then
  12103. SetResolverValueExpr(ResolvedEl,btDouble,FBaseTypes[btDouble],TPrimitiveExpr(El),[rrfReadable])
  12104. else
  12105. SetResolverValueExpr(ResolvedEl,btLongint,FBaseTypes[btLongint],TPrimitiveExpr(El),[rrfReadable]);
  12106. pekString:
  12107. begin
  12108. {$IFDEF VerbosePasResolver}
  12109. writeln('TPasResolver.ComputeElement pekString Value="',TPrimitiveExpr(El).Value,'"');
  12110. {$ENDIF}
  12111. bt:=IsCharLiteral(TPrimitiveExpr(El).Value,El);
  12112. if bt in btAllChars then
  12113. begin
  12114. if bt=BaseTypeChar then
  12115. bt:=btChar;
  12116. SetResolverValueExpr(ResolvedEl,bt,FBaseTypes[bt],TPrimitiveExpr(El),[rrfReadable]);
  12117. end
  12118. else
  12119. SetResolverValueExpr(ResolvedEl,btString,FBaseTypes[btString],TPrimitiveExpr(El),[rrfReadable]);
  12120. end;
  12121. pekNil:
  12122. SetResolverValueExpr(ResolvedEl,btNil,FBaseTypes[btNil],TPrimitiveExpr(El),[rrfReadable]);
  12123. pekBoolConst:
  12124. SetResolverValueExpr(ResolvedEl,btBoolean,FBaseTypes[btBoolean],TPrimitiveExpr(El),[rrfReadable]);
  12125. else
  12126. RaiseNotYetImplemented(20160922163701,El);
  12127. end;
  12128. end
  12129. else if ElClass=TSelfExpr then
  12130. begin
  12131. // self is just an identifier
  12132. if not (El.CustomData is TResolvedReference) then
  12133. RaiseNotYetImplemented(20170216150017,El,' El="'+GetObjName(El)+'" CustomData='+GetObjName(El.CustomData)+' '+GetElementSourcePosStr(El));
  12134. ComputeIdentifier(TSelfExpr(El));
  12135. end
  12136. else if ElClass=TPasUnresolvedSymbolRef then
  12137. begin
  12138. // built-in type
  12139. if El.CustomData is TResElDataBaseType then
  12140. SetResolverIdentifier(ResolvedEl,TResElDataBaseType(El.CustomData).BaseType,
  12141. El,TPasUnresolvedSymbolRef(El),[])
  12142. else if El.CustomData is TResElDataBuiltInProc then
  12143. begin
  12144. SetResolverIdentifier(ResolvedEl,btBuiltInProc,El,TPasUnresolvedSymbolRef(El),[]);
  12145. if bipfCanBeStatement in TResElDataBuiltInProc(El.CustomData).Flags then
  12146. Include(ResolvedEl.Flags,rrfCanBeStatement);
  12147. end
  12148. else
  12149. RaiseNotYetImplemented(20160926194756,El);
  12150. end
  12151. else if ElClass=TBoolConstExpr then
  12152. SetResolverValueExpr(ResolvedEl,btBoolean,FBaseTypes[btBoolean],TBoolConstExpr(El),[rrfReadable])
  12153. else if ElClass=TBinaryExpr then
  12154. ComputeBinaryExpr(TBinaryExpr(El),ResolvedEl,Flags,StartEl)
  12155. else if ElClass=TUnaryExpr then
  12156. begin
  12157. if TUnaryExpr(El).OpCode in [eopAddress,eopMemAddress] then
  12158. ComputeElement(TUnaryExpr(El).Operand,ResolvedEl,Flags+[rcNoImplicitProc],StartEl)
  12159. else
  12160. ComputeElement(TUnaryExpr(El).Operand,ResolvedEl,Flags,StartEl);
  12161. {$IFDEF VerbosePasResolver}
  12162. writeln('TPasResolver.ComputeElement Unary Kind=',TUnaryExpr(El).Kind,' OpCode=',TUnaryExpr(El).OpCode,' OperandResolved=',GetResolverResultDbg(ResolvedEl),' ',GetElementSourcePosStr(El));
  12163. {$ENDIF}
  12164. case TUnaryExpr(El).OpCode of
  12165. eopAdd, eopSubtract:
  12166. if ResolvedEl.BaseType in (btAllInteger+btAllFloats) then
  12167. exit
  12168. else
  12169. RaiseMsg(20170216152532,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TUnaryExpr(El).OpCode]],El);
  12170. eopNot:
  12171. if ResolvedEl.BaseType in (btAllInteger+btAllBooleans) then
  12172. exit
  12173. else
  12174. RaiseMsg(20170216152534,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TUnaryExpr(El).OpCode]],El);
  12175. eopAddress:
  12176. if (ResolvedEl.BaseType=btProc) and (ResolvedEl.IdentEl is TPasProcedure) then
  12177. begin
  12178. SetResolverValueExpr(ResolvedEl,btContext,ResolvedEl.TypeEl,TUnaryExpr(El).Operand,[rrfReadable]);
  12179. exit;
  12180. end
  12181. else
  12182. RaiseMsg(20170216152535,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TUnaryExpr(El).OpCode]],El);
  12183. eopMemAddress:
  12184. begin
  12185. if (ResolvedEl.BaseType=btContext) and (ResolvedEl.TypeEl is TPasProcedureType) then
  12186. exit
  12187. else
  12188. RaiseMsg(20170902145547,nIllegalQualifier,sIllegalQualifier,[OpcodeStrings[TUnaryExpr(El).OpCode]],El);
  12189. end;
  12190. end;
  12191. RaiseNotYetImplemented(20160926142426,El);
  12192. end
  12193. else if ElClass=TParamsExpr then
  12194. case TParamsExpr(El).Kind of
  12195. pekArrayParams:
  12196. ComputeArrayParams(TParamsExpr(El),ResolvedEl,Flags,StartEl);
  12197. pekFuncParams:
  12198. ComputeFuncParams(TParamsExpr(El),ResolvedEl,Flags,StartEl);
  12199. pekSet:
  12200. ComputeSetParams(TParamsExpr(El),ResolvedEl,Flags,StartEl);
  12201. else
  12202. RaiseNotYetImplemented(20161010184559,El);
  12203. end
  12204. else if ElClass=TInheritedExpr then
  12205. begin
  12206. // writeln('TPasResolver.ComputeElement TInheritedExpr El.CustomData=',GetObjName(El.CustomData));
  12207. if El.CustomData is TResolvedReference then
  12208. begin
  12209. // "inherited;"
  12210. DeclEl:=TResolvedReference(El.CustomData).Declaration as TPasProcedure;
  12211. SetResolverIdentifier(ResolvedEl,btProc,DeclEl,
  12212. TPasProcedure(DeclEl).ProcType,[rrfCanBeStatement]);
  12213. end
  12214. else
  12215. // no ancestor proc
  12216. SetResolverIdentifier(ResolvedEl,btBuiltInProc,nil,nil,[rrfCanBeStatement]);
  12217. end
  12218. else if ElClass=TPasAliasType then
  12219. begin
  12220. // e.g. 'type a = b' -> compute b
  12221. ComputeElement(TPasAliasType(El).DestType,ResolvedEl,Flags+[rcType],StartEl);
  12222. ResolvedEl.IdentEl:=El;
  12223. end
  12224. else if (ElClass=TPasTypeAliasType) then
  12225. begin
  12226. // e.g. 'type a = type b;' -> compute b
  12227. ComputeElement(TPasTypeAliasType(El).DestType,ResolvedEl,Flags+[rcType],StartEl);
  12228. if not (rcSkipTypeAlias in Flags) then
  12229. ResolvedEl.IdentEl:=El;
  12230. end
  12231. else if (ElClass=TPasVariable) then
  12232. begin
  12233. // e.g. 'var a:b' -> compute b, use a as IdentEl
  12234. if rcConstant in Flags then
  12235. RaiseConstantExprExp(20170216152737,StartEl);
  12236. ComputeElement(TPasVariable(El).VarType,ResolvedEl,Flags+[rcType],StartEl);
  12237. ResolvedEl.IdentEl:=El;
  12238. ResolvedEl.Flags:=[rrfReadable,rrfWritable];
  12239. end
  12240. else if (ElClass=TPasConst) then
  12241. begin
  12242. // e.g. 'var a:b' -> compute b, use a as IdentEl
  12243. if TPasConst(El).VarType<>nil then
  12244. begin
  12245. // typed const -> just like a var
  12246. if rcConstant in Flags then
  12247. RaiseConstantExprExp(20170216152739,StartEl);
  12248. ComputeElement(TPasConst(El).VarType,ResolvedEl,Flags+[rcType],StartEl);
  12249. ResolvedEl.IdentEl:=El;
  12250. ResolvedEl.Flags:=[rrfReadable,rrfWritable];
  12251. end
  12252. else
  12253. begin
  12254. // untyped const
  12255. ComputeElement(TPasConst(El).Expr,ResolvedEl,Flags+[rcConstant],StartEl);
  12256. ResolvedEl.IdentEl:=El;
  12257. ResolvedEl.Flags:=[rrfReadable];
  12258. end;
  12259. end
  12260. else if (ElClass=TPasEnumValue) then
  12261. SetResolverIdentifier(ResolvedEl,btContext,El,El.Parent as TPasEnumType,[rrfReadable])
  12262. else if (ElClass=TPasEnumType) then
  12263. SetResolverIdentifier(ResolvedEl,btContext,El,TPasEnumType(El),[])
  12264. else if (ElClass=TPasProperty) then
  12265. begin
  12266. if rcConstant in Flags then
  12267. RaiseConstantExprExp(20170216152741,StartEl);
  12268. if TPasProperty(El).Args.Count=0 then
  12269. begin
  12270. ComputeElement(GetPasPropertyType(TPasProperty(El)),ResolvedEl,
  12271. Flags+[rcType],StartEl);
  12272. ResolvedEl.IdentEl:=El;
  12273. ResolvedEl.Flags:=[];
  12274. if GetPasPropertyGetter(TPasProperty(El))<>nil then
  12275. Include(ResolvedEl.Flags,rrfReadable);
  12276. if GetPasPropertySetter(TPasProperty(El))<>nil then
  12277. Include(ResolvedEl.Flags,rrfWritable);
  12278. if IsProcedureType(ResolvedEl,true) then
  12279. Include(ResolvedEl.Flags,rrfCanBeStatement);
  12280. end
  12281. else
  12282. // index property
  12283. SetResolverIdentifier(ResolvedEl,btContext,El,nil,[]);
  12284. end
  12285. else if ElClass=TPasArgument then
  12286. begin
  12287. if rcConstant in Flags then
  12288. RaiseConstantExprExp(20170216152744,StartEl);
  12289. if TPasArgument(El).ArgType=nil then
  12290. // untyped parameter
  12291. SetResolverIdentifier(ResolvedEl,btUntyped,El,nil,[])
  12292. else
  12293. begin
  12294. // typed parameter -> use param as IdentEl, compute type
  12295. ComputeElement(TPasArgument(El).ArgType,ResolvedEl,Flags+[rcType],StartEl);
  12296. ResolvedEl.IdentEl:=El;
  12297. end;
  12298. ResolvedEl.Flags:=[rrfReadable];
  12299. if TPasArgument(El).Access in [argDefault, argVar, argOut] then
  12300. Include(ResolvedEl.Flags,rrfWritable);
  12301. if IsProcedureType(ResolvedEl,true) then
  12302. Include(ResolvedEl.Flags,rrfCanBeStatement);
  12303. end
  12304. else if ElClass=TPasClassType then
  12305. begin
  12306. if TPasClassType(El).IsForward and (El.CustomData<>nil) then
  12307. begin
  12308. DeclEl:=(TPasClassType(El).CustomData as TResolvedReference).Declaration;
  12309. ResolvedEl.TypeEl:=DeclEl as TPasClassType;
  12310. end
  12311. else
  12312. ResolvedEl.TypeEl:=TPasClassType(El);
  12313. SetResolverIdentifier(ResolvedEl,btContext,
  12314. ResolvedEl.TypeEl,ResolvedEl.TypeEl,[]);
  12315. end
  12316. else if ElClass=TPasClassOfType then
  12317. SetResolverIdentifier(ResolvedEl,btContext,El,TPasClassOfType(El),[])
  12318. else if ElClass=TPasRecordType then
  12319. SetResolverIdentifier(ResolvedEl,btContext,El,TPasRecordType(El),[])
  12320. else if ElClass=TPasRangeType then
  12321. begin
  12322. ComputeElement(TPasRangeType(El).RangeExpr,ResolvedEl,[rcConstant],StartEl);
  12323. ResolvedEl.IdentEl:=El;
  12324. if ResolvedEl.ExprEl=nil then
  12325. ResolvedEl.ExprEl:=TPasRangeType(El).RangeExpr;
  12326. ResolvedEl.Flags:=[];
  12327. end
  12328. else if ElClass=TPasSetType then
  12329. begin
  12330. ComputeElement(TPasSetType(El).EnumType,ResolvedEl,[rcConstant],StartEl);
  12331. if ResolvedEl.BaseType=btRange then
  12332. ConvertRangeToFirstValue(ResolvedEl);
  12333. ResolvedEl.SubType:=ResolvedEl.BaseType;
  12334. ResolvedEl.BaseType:=btSet;
  12335. ResolvedEl.IdentEl:=El;
  12336. ResolvedEl.Flags:=[];
  12337. end
  12338. else if ElClass=TPasResultElement then
  12339. begin
  12340. if rcConstant in Flags then
  12341. RaiseConstantExprExp(20170216152746,StartEl);
  12342. ComputeElement(TPasResultElement(El).ResultType,ResolvedEl,Flags+[rcType],StartEl);
  12343. ResolvedEl.IdentEl:=El;
  12344. ResolvedEl.Flags:=[rrfReadable,rrfWritable];
  12345. end
  12346. else if ElClass=TPasUsesUnit then
  12347. begin
  12348. if TPasUsesUnit(El).Module is TPasModule then
  12349. SetResolverIdentifier(ResolvedEl,btModule,TPasUsesUnit(El).Module,nil,[])
  12350. else
  12351. RaiseNotYetImplemented(20170429112047,TPasUsesUnit(El).Module);
  12352. end
  12353. else if El.InheritsFrom(TPasModule) then
  12354. SetResolverIdentifier(ResolvedEl,btModule,El,nil,[])
  12355. else if ElClass=TNilExpr then
  12356. SetResolverValueExpr(ResolvedEl,btNil,FBaseTypes[btNil],TNilExpr(El),[rrfReadable])
  12357. else if El.InheritsFrom(TPasProcedure) then
  12358. begin
  12359. SetResolverIdentifier(ResolvedEl,btProc,El,TPasProcedure(El).ProcType,[rrfCanBeStatement]);
  12360. if El is TPasFunction then
  12361. Include(ResolvedEl.Flags,rrfReadable);
  12362. // Note: the readability of TPasConstructor depends on the context
  12363. // Note: implicit calls are handled in TPrimitiveExpr
  12364. end
  12365. else if El.InheritsFrom(TPasProcedureType) then
  12366. begin
  12367. SetResolverIdentifier(ResolvedEl,btContext,El,TPasProcedureType(El),[rrfCanBeStatement]);
  12368. // Note: implicit calls are handled in TPrimitiveExpr
  12369. end
  12370. else if ElClass=TPasArrayType then
  12371. SetResolverIdentifier(ResolvedEl,btContext,El,TPasArrayType(El),[])
  12372. else if ElClass=TArrayValues then
  12373. SetResolverValueExpr(ResolvedEl,btSet,nil,TArrayValues(El),[rrfReadable])
  12374. else if ElClass=TPasStringType then
  12375. begin
  12376. SetResolverTypeExpr(ResolvedEl,btShortString,BaseTypes[btShortString],[rrfReadable]);
  12377. if BaseTypes[btShortString]=nil then
  12378. RaiseMsg(20170419203146,nIllegalQualifier,sIllegalQualifier,['['],El);
  12379. end
  12380. else
  12381. RaiseNotYetImplemented(20160922163705,El);
  12382. end;
  12383. function TPasResolver.IsSameType(TypeA, TypeB: TPasType; ResolveAlias: boolean
  12384. ): boolean;
  12385. begin
  12386. if (TypeA=nil) or (TypeB=nil) then exit(false);
  12387. if ResolveAlias then
  12388. begin
  12389. TypeA:=ResolveAliasType(TypeA);
  12390. TypeB:=ResolveAliasType(TypeB);
  12391. end;
  12392. if TypeA=TypeB then exit(true);
  12393. if (TypeA.ClassType=TPasUnresolvedSymbolRef)
  12394. and (TypeB.ClassType=TPasUnresolvedSymbolRef) then
  12395. begin
  12396. Result:=CompareText(TypeA.Name,TypeB.Name)=0;
  12397. exit;
  12398. end;
  12399. Result:=false;
  12400. end;
  12401. function TPasResolver.GetPasClassAncestor(ClassEl: TPasClassType;
  12402. SkipAlias: boolean): TPasType;
  12403. var
  12404. DeclEl: TPasElement;
  12405. ClassScope: TPasClassScope;
  12406. begin
  12407. Result:=nil;
  12408. if ClassEl=nil then
  12409. exit;
  12410. if ClassEl.CustomData=nil then
  12411. exit;
  12412. if ClassEl.IsForward then
  12413. begin
  12414. DeclEl:=(ClassEl.CustomData as TResolvedReference).Declaration;
  12415. ClassEl:=DeclEl as TPasClassType;
  12416. Result:=ClassEl;
  12417. end
  12418. else
  12419. begin
  12420. ClassScope:=ClassEl.CustomData as TPasClassScope;
  12421. if not (pcsfAncestorResolved in ClassScope.Flags) then
  12422. exit;
  12423. if SkipAlias then
  12424. begin
  12425. if ClassScope.AncestorScope=nil then
  12426. exit;
  12427. Result:=TPasClassType(ClassScope.AncestorScope.Element);
  12428. end
  12429. else
  12430. Result:=ClassScope.DirectAncestor;
  12431. end;
  12432. end;
  12433. function TPasResolver.GetLoop(El: TPasElement): TPasImplElement;
  12434. begin
  12435. while El<>nil do
  12436. begin
  12437. if (El.ClassType=TPasImplRepeatUntil)
  12438. or (El.ClassType=TPasImplWhileDo)
  12439. or (El.ClassType=TPasImplForLoop) then
  12440. exit(TPasImplElement(El));
  12441. El:=El.Parent;
  12442. end;
  12443. Result:=nil;
  12444. end;
  12445. function TPasResolver.ResolveAliasType(aType: TPasType): TPasType;
  12446. var
  12447. C: TClass;
  12448. begin
  12449. Result:=aType;
  12450. while Result<>nil do
  12451. begin
  12452. C:=Result.ClassType;
  12453. if (C=TPasAliasType) or (C=TPasTypeAliasType) then
  12454. Result:=TPasAliasType(Result).DestType
  12455. else if (C=TPasClassType) and TPasClassType(Result).IsForward
  12456. and (Result.CustomData is TResolvedReference) then
  12457. Result:=TResolvedReference(Result.CustomData).Declaration as TPasType
  12458. else
  12459. exit;
  12460. end;
  12461. end;
  12462. function TPasResolver.ExprIsAddrTarget(El: TPasExpr): boolean;
  12463. { returns true if El is
  12464. a) the last element of an @ operator expression
  12465. e.g. '@p().o[].El' or '@El[]'
  12466. b) mode delphi: the last element of a right side of an assignment
  12467. c) an accessor function, e.g. property P read El;
  12468. }
  12469. var
  12470. Parent: TPasElement;
  12471. Prop: TPasProperty;
  12472. begin
  12473. Result:=false;
  12474. if El=nil then exit;
  12475. if not IsNameExpr(El) then
  12476. exit;
  12477. repeat
  12478. Parent:=El.Parent;
  12479. //writeln('TPasResolver.ExprIsAddrTarget El=',GetObjName(El),' Parent=',GetObjName(Parent));
  12480. if Parent.ClassType=TUnaryExpr then
  12481. begin
  12482. if TUnaryExpr(Parent).OpCode=eopAddress then exit(true);
  12483. end
  12484. else if Parent.ClassType=TBinaryExpr then
  12485. begin
  12486. if TBinaryExpr(Parent).right<>El then exit;
  12487. if TBinaryExpr(Parent).OpCode<>eopSubIdent then exit;
  12488. end
  12489. else if Parent.ClassType=TParamsExpr then
  12490. begin
  12491. if TParamsExpr(Parent).Value<>El then exit;
  12492. end
  12493. else if Parent.ClassType=TPasProperty then
  12494. begin
  12495. Prop:=TPasProperty(Parent);
  12496. Result:=(Prop.ReadAccessor=El) or (Prop.WriteAccessor=El) or (Prop.StoredAccessor=El);
  12497. exit;
  12498. end
  12499. else if Parent.ClassType=TPasImplAssign then
  12500. begin
  12501. if TPasImplAssign(Parent).right<>El then exit;
  12502. if (msDelphi in CurrentParser.CurrentModeswitches) then exit(true);
  12503. exit;
  12504. end
  12505. else
  12506. exit;
  12507. El:=TPasExpr(Parent);
  12508. until false;
  12509. end;
  12510. function TPasResolver.ParentNeedsExprResult(El: TPasExpr): boolean;
  12511. var
  12512. C: TClass;
  12513. P: TPasElement;
  12514. begin
  12515. if (El=nil) or (El.Parent=nil) then exit(false);
  12516. Result:=false;
  12517. P:=El.Parent;
  12518. C:=P.ClassType;
  12519. if C=TBinaryExpr then
  12520. begin
  12521. if TBinaryExpr(P).right=El then
  12522. begin
  12523. if (TBinaryExpr(P).OpCode=eopSubIdent)
  12524. or ((TBinaryExpr(P).OpCode=eopNone) and (TBinaryExpr(P).left is TInheritedExpr)) then
  12525. Result:=ParentNeedsExprResult(TBinaryExpr(P))
  12526. else
  12527. Result:=true;
  12528. end
  12529. else
  12530. Result:=true;
  12531. end
  12532. else if C.InheritsFrom(TPasExpr) then
  12533. Result:=true
  12534. else if (C=TPasEnumValue)
  12535. or (C=TPasArgument)
  12536. or (C=TPasVariable)
  12537. or (C=TPasExportSymbol) then
  12538. Result:=true
  12539. else if C=TPasClassType then
  12540. Result:=TPasClassType(P).GUIDExpr=El
  12541. else if C=TPasProperty then
  12542. Result:=(TPasProperty(P).IndexExpr=El)
  12543. or (TPasProperty(P).DispIDExpr=El)
  12544. or (TPasProperty(P).DefaultExpr=El)
  12545. else if C=TPasProcedure then
  12546. Result:=(TPasProcedure(P).LibraryExpr=El)
  12547. or (TPasProcedure(P).DispIDExpr=El)
  12548. else if C=TPasImplRepeatUntil then
  12549. Result:=(TPasImplRepeatUntil(P).ConditionExpr=El)
  12550. else if C=TPasImplIfElse then
  12551. Result:=(TPasImplIfElse(P).ConditionExpr=El)
  12552. else if C=TPasImplWhileDo then
  12553. Result:=(TPasImplWhileDo(P).ConditionExpr=El)
  12554. else if C=TPasImplWithDo then
  12555. Result:=(TPasImplWithDo(P).Expressions.IndexOf(El)>=0)
  12556. else if C=TPasImplCaseOf then
  12557. Result:=(TPasImplCaseOf(P).CaseExpr=El)
  12558. else if C=TPasImplCaseStatement then
  12559. Result:=(TPasImplCaseStatement(P).Expressions.IndexOf(El)>=0)
  12560. else if C=TPasImplForLoop then
  12561. Result:=(TPasImplForLoop(P).StartExpr=El)
  12562. or (TPasImplForLoop(P).EndExpr=El)
  12563. else if C=TPasImplAssign then
  12564. Result:=(TPasImplAssign(P).right=El)
  12565. else if C=TPasImplRaise then
  12566. Result:=(TPasImplRaise(P).ExceptAddr=El);
  12567. end;
  12568. function TPasResolver.GetReference_NewInstanceClass(Ref: TResolvedReference
  12569. ): TPasClassType;
  12570. begin
  12571. Result:=(Ref.Context as TResolvedRefCtxConstructor).Typ as TPasClassType;
  12572. end;
  12573. function TPasResolver.IsDynArray(TypeEl: TPasType): boolean;
  12574. begin
  12575. if (TypeEl=nil) or (TypeEl.ClassType<>TPasArrayType)
  12576. or (length(TPasArrayType(TypeEl).Ranges)<>0) then
  12577. exit(false);
  12578. if proOpenAsDynArrays in Options then
  12579. Result:=true
  12580. else
  12581. Result:=(TypeEl.Parent=nil) or (TypeEl.Parent.ClassType<>TPasArgument);
  12582. end;
  12583. function TPasResolver.IsOpenArray(TypeEl: TPasType): boolean;
  12584. begin
  12585. Result:=(TypeEl<>nil)
  12586. and (TypeEl.ClassType=TPasArrayType)
  12587. and (length(TPasArrayType(TypeEl).Ranges)=0)
  12588. and (TypeEl.Parent<>nil)
  12589. and (TypeEl.Parent.ClassType=TPasArgument);
  12590. end;
  12591. function TPasResolver.IsDynOrOpenArray(TypeEl: TPasType): boolean;
  12592. begin
  12593. Result:=(TypeEl<>nil) and (TypeEl.ClassType=TPasArrayType)
  12594. and (length(TPasArrayType(TypeEl).Ranges)=0);
  12595. end;
  12596. function TPasResolver.IsVarInit(Expr: TPasExpr): boolean;
  12597. var
  12598. C: TClass;
  12599. begin
  12600. Result:=false;
  12601. if Expr=nil then exit;
  12602. if Expr.Parent=nil then exit;
  12603. C:=Expr.Parent.ClassType;
  12604. if C.InheritsFrom(TPasVariable) then
  12605. Result:=(TPasVariable(Expr.Parent).Expr=Expr)
  12606. else if C=TPasArgument then
  12607. Result:=(TPasArgument(Expr.Parent).ValueExpr=Expr);
  12608. end;
  12609. function TPasResolver.IsEmptySet(const ResolvedEl: TPasResolverResult): boolean;
  12610. begin
  12611. Result:=(ResolvedEl.BaseType=btSet) and (ResolvedEl.SubType=btNone);
  12612. end;
  12613. function TPasResolver.IsClassMethod(El: TPasElement): boolean;
  12614. var
  12615. C: TClass;
  12616. begin
  12617. if El=nil then exit(false);
  12618. C:=El.ClassType;;
  12619. Result:=(C=TPasClassConstructor)
  12620. or (C=TPasClassDestructor)
  12621. or (C=TPasClassProcedure)
  12622. or (C=TPasClassFunction)
  12623. or (C=TPasClassOperator);
  12624. end;
  12625. function TPasResolver.IsExternalClassName(aClass: TPasClassType;
  12626. const ExtName: string): boolean;
  12627. var
  12628. AncestorScope: TPasClassScope;
  12629. begin
  12630. Result:=false;
  12631. if aClass=nil then exit;
  12632. while (aClass<>nil) and aClass.IsExternal do
  12633. begin
  12634. if aClass.ExternalName=ExtName then exit(true);
  12635. AncestorScope:=(aClass.CustomData as TPasClassScope).AncestorScope;
  12636. if AncestorScope=nil then exit;
  12637. aClass:=AncestorScope.Element as TPasClassType;
  12638. end;
  12639. end;
  12640. function TPasResolver.IsProcedureType(const ResolvedEl: TPasResolverResult;
  12641. HasValue: boolean): boolean;
  12642. begin
  12643. if (ResolvedEl.BaseType<>btContext) or not (ResolvedEl.TypeEl is TPasProcedureType) then
  12644. exit(false);
  12645. if HasValue and not (rrfReadable in ResolvedEl.Flags) then
  12646. exit(false);
  12647. Result:=true;
  12648. end;
  12649. function TPasResolver.IsArrayType(const ResolvedEl: TPasResolverResult
  12650. ): boolean;
  12651. begin
  12652. Result:=(ResolvedEl.BaseType=btContext) and (ResolvedEl.TypeEl is TPasArrayType);
  12653. end;
  12654. function TPasResolver.IsTypeCast(Params: TParamsExpr): boolean;
  12655. var
  12656. Value: TPasExpr;
  12657. Ref: TResolvedReference;
  12658. Decl: TPasElement;
  12659. C: TClass;
  12660. begin
  12661. Result:=false;
  12662. if (Params=nil) or (Params.Kind<>pekFuncParams) then exit;
  12663. Value:=Params.Value;
  12664. if not IsNameExpr(Value) then
  12665. exit;
  12666. if not (Value.CustomData is TResolvedReference) then exit;
  12667. Ref:=TResolvedReference(Value.CustomData);
  12668. Decl:=Ref.Declaration;
  12669. C:=Decl.ClassType;
  12670. if (C=TPasAliasType) or (C=TPasTypeAliasType) then
  12671. begin
  12672. Decl:=ResolveAliasType(TPasAliasType(Decl));
  12673. C:=Decl.ClassType;
  12674. end;
  12675. if (C=TPasProcedureType)
  12676. or (C=TPasFunctionType) then
  12677. exit(true)
  12678. else if (C=TPasClassType)
  12679. or (C=TPasClassOfType)
  12680. or (C=TPasEnumType) then
  12681. exit(true)
  12682. else if (C=TPasUnresolvedSymbolRef)
  12683. and (Decl.CustomData is TResElDataBaseType) then
  12684. exit(true);
  12685. end;
  12686. function TPasResolver.ProcNeedsParams(El: TPasProcedureType): boolean;
  12687. begin
  12688. Result:=(El.Args.Count>0) and (TPasArgument(El.Args[0]).ValueExpr=nil);
  12689. end;
  12690. function TPasResolver.GetRangeLength(const RangeResolved: TPasResolverResult
  12691. ): MaxPrecInt;
  12692. var
  12693. TypeEl: TPasType;
  12694. Value: TResEvalValue;
  12695. begin
  12696. Result:=0;
  12697. if RangeResolved.BaseType=btContext then
  12698. begin
  12699. if RangeResolved.IdentEl is TPasType then
  12700. begin
  12701. TypeEl:=ResolveAliasType(TPasType(RangeResolved.IdentEl));
  12702. if TypeEl<>nil then
  12703. begin
  12704. if TypeEl.ClassType=TPasEnumType then
  12705. Result:=TPasEnumType(TypeEl).Values.Count;
  12706. end;
  12707. end;
  12708. end
  12709. else if RangeResolved.ExprEl<>nil then
  12710. begin
  12711. Value:=Eval(RangeResolved.ExprEl,[]);
  12712. if Value=nil then
  12713. RaiseMsg(20170729094135,nIncompatibleTypesGotExpected,
  12714. sIncompatibleTypesGotExpected,
  12715. [GetResolverResultDescription(RangeResolved),'range'],RangeResolved.ExprEl);
  12716. try
  12717. case Value.Kind of
  12718. revkRangeInt:
  12719. Result:=TResEvalRangeInt(Value).RangeEnd-TResEvalRangeInt(Value).RangeStart+1;
  12720. else
  12721. RaiseMsg(20170729093823,nIncompatibleTypesGotExpected,
  12722. sIncompatibleTypesGotExpected,
  12723. [GetResolverResultDescription(RangeResolved),'range'],RangeResolved.ExprEl);
  12724. end;
  12725. finally
  12726. ReleaseEvalValue(Value);
  12727. end;
  12728. end
  12729. else if RangeResolved.BaseType in btAllBooleans then
  12730. Result:=2;
  12731. {$IFDEF VerbosePasResolver}
  12732. //if Result=0 then
  12733. writeln('TPasResolver.GetRangeLength ',GetResolverResultDbg(RangeResolved),' Result=',Result);
  12734. {$ENDIF}
  12735. end;
  12736. function TPasResolver.EvalRangeLimit(RangeExpr: TPasExpr; Flags: TResEvalFlags;
  12737. EvalLow: boolean; ErrorEl: TPasElement): TResEvalValue;
  12738. var
  12739. Range: TResEvalValue;
  12740. EnumType: TPasEnumType;
  12741. begin
  12742. Result:=nil;
  12743. Range:=Eval(RangeExpr,Flags+[refConst]);
  12744. if Range=nil then
  12745. RaiseNotYetImplemented(20170601191258,RangeExpr);
  12746. case Range.Kind of
  12747. revkRangeInt:
  12748. case TResEvalRangeInt(Range).ElKind of
  12749. revskEnum:
  12750. begin
  12751. EnumType:=TResEvalRangeInt(Range).ElType as TPasEnumType;
  12752. if EvalLow then
  12753. Result:=TResEvalEnum.CreateValue(
  12754. TResEvalRangeInt(Range).RangeStart,TPasEnumValue(EnumType.Values[0]))
  12755. else
  12756. Result:=TResEvalEnum.CreateValue(
  12757. TResEvalRangeInt(Range).RangeEnd,
  12758. TPasEnumValue(EnumType.Values[EnumType.Values.Count-1]));
  12759. end;
  12760. revskInt:
  12761. if EvalLow then
  12762. Result:=TResEvalInt.CreateValue(TResEvalRangeInt(Range).RangeStart)
  12763. else
  12764. Result:=TResEvalInt.CreateValue(TResEvalRangeInt(Range).RangeEnd);
  12765. revskChar:
  12766. if EvalLow then
  12767. Result:=TResEvalString.CreateValue(chr(TResEvalRangeInt(Range).RangeStart))
  12768. else if TResEvalRangeInt(Range).RangeEnd<256 then
  12769. Result:=TResEvalString.CreateValue(chr(TResEvalRangeInt(Range).RangeEnd))
  12770. else
  12771. Result:=TResEvalUTF16.CreateValue(widechar(TResEvalRangeInt(Range).RangeEnd));
  12772. revskBool:
  12773. if EvalLow then
  12774. Result:=TResEvalBool.CreateValue(low(Boolean))
  12775. else
  12776. Result:=TResEvalBool.CreateValue(high(Boolean));
  12777. else
  12778. RaiseNotYetImplemented(20170601195240,ErrorEl);
  12779. end;
  12780. revkRangeUInt:
  12781. if EvalLow then
  12782. Result:=TResEvalUInt.CreateValue(TResEvalRangeUInt(Range).RangeStart)
  12783. else
  12784. Result:=TResEvalUInt.CreateValue(TResEvalRangeUInt(Range).RangeEnd);
  12785. else
  12786. RaiseNotYetImplemented(20170601195336,ErrorEl);
  12787. end;
  12788. end;
  12789. function TPasResolver.HasTypeInfo(El: TPasType): boolean;
  12790. begin
  12791. Result:=false;
  12792. if El=nil then exit;
  12793. if El.CustomData is TResElDataBaseType then
  12794. exit(true); // base type
  12795. if El.Parent=nil then exit;
  12796. if (El.Parent is TPasType) and not HasTypeInfo(TPasType(El.Parent)) then
  12797. exit;
  12798. Result:=true;
  12799. end;
  12800. function TPasResolver.GetActualBaseType(bt: TResolverBaseType
  12801. ): TResolverBaseType;
  12802. begin
  12803. case bt of
  12804. btChar: Result:=BaseTypeChar;
  12805. btString: Result:=BaseTypeString;
  12806. btExtended: Result:=BaseTypeExtended;
  12807. else Result:=bt;
  12808. end;
  12809. end;
  12810. function TPasResolver.GetCombinedBoolean(Bool1, Bool2: TResolverBaseType;
  12811. ErrorEl: TPasElement): TResolverBaseType;
  12812. begin
  12813. if Bool1=Bool2 then exit(Bool1);
  12814. case Bool1 of
  12815. btBoolean: Result:=Bool2;
  12816. btByteBool: if Bool2<>btBoolean then Result:=Bool2;
  12817. btWordBool: if not (Bool2 in [btBoolean,btByteBool]) then Result:=Bool2;
  12818. btLongBool: if not (Bool2 in [btBoolean,btByteBool,btWordBool]) then Result:=Bool2;
  12819. btQWordBool: if not (Bool2 in [btBoolean,btByteBool,btWordBool,btLongBool]) then Result:=Bool2;
  12820. else
  12821. RaiseNotYetImplemented(20170420093805,ErrorEl);
  12822. end;
  12823. end;
  12824. function TPasResolver.GetCombinedInt(const Int1, Int2: TPasResolverResult;
  12825. ErrorEl: TPasElement): TResolverBaseType;
  12826. var
  12827. Precision1, Precision2: word;
  12828. Signed1, Signed2: boolean;
  12829. begin
  12830. if Int1.BaseType=Int2.BaseType then exit;
  12831. GetIntegerProps(Int1.BaseType,Precision1,Signed1);
  12832. GetIntegerProps(Int2.BaseType,Precision2,Signed2);
  12833. if Precision1=Precision2 then
  12834. begin
  12835. if Signed1<>Signed2 then
  12836. Precision1:=Max(Precision1,Precision2)+1;
  12837. end;
  12838. Result:=GetIntegerBaseType(Max(Precision1,Precision2),Signed1 or Signed2,ErrorEl);
  12839. end;
  12840. procedure TPasResolver.GetIntegerProps(bt: TResolverBaseType; out
  12841. Precision: word; out Signed: boolean);
  12842. begin
  12843. case bt of
  12844. btByte: begin Precision:=8; Signed:=false; end;
  12845. btShortInt: begin Precision:=8; Signed:=true; end;
  12846. btWord: begin Precision:=16; Signed:=false; end;
  12847. btSmallInt: begin Precision:=16; Signed:=true; end;
  12848. btIntSingle: begin Precision:=23; Signed:=true; end;
  12849. btUIntSingle: begin Precision:=22; Signed:=false; end;
  12850. btLongWord: begin Precision:=32; Signed:=false; end;
  12851. btLongint: begin Precision:=32; Signed:=true; end;
  12852. btIntDouble: begin Precision:=53; Signed:=true; end;
  12853. btUIntDouble: begin Precision:=52; Signed:=false; end;
  12854. btQWord: begin Precision:=64; Signed:=false; end;
  12855. btInt64,btComp: begin Precision:=64; Signed:=true; end;
  12856. else
  12857. RaiseInternalError(20170420095727);
  12858. end;
  12859. end;
  12860. function TPasResolver.GetIntegerRange(bt: TResolverBaseType; out MinVal,
  12861. MaxVal: int64): boolean;
  12862. begin
  12863. Result:=true;
  12864. if bt=btExtended then bt:=BaseTypeExtended;
  12865. case bt of
  12866. btByte: begin MinVal:=Low(byte); MaxVal:=High(byte); end;
  12867. btShortInt: begin MinVal:=low(ShortInt); MaxVal:=high(ShortInt); end;
  12868. btWord: begin MinVal:=low(word); MaxVal:=high(word); end;
  12869. btSmallInt: begin MinVal:=low(SmallInt); MaxVal:=high(SmallInt); end;
  12870. btLongWord: begin MinVal:=low(LongWord); MaxVal:=high(LongWord); end;
  12871. btLongint: begin MinVal:=low(LongInt); MaxVal:=high(LongInt); end;
  12872. btInt64,btComp: begin MinVal:=low(int64); MaxVal:=high(int64); end;
  12873. btSingle,btIntSingle: begin MinVal:=MinSafeIntSingle; MaxVal:=MaxSafeIntSingle; end;
  12874. btUIntSingle: begin MinVal:=0; MaxVal:=MaxSafeIntSingle; end;
  12875. btDouble,btIntDouble: begin MinVal:=MinSafeIntDouble; MaxVal:=MaxSafeIntDouble; end;
  12876. btUIntDouble: begin MinVal:=0; MaxVal:=MaxSafeIntDouble; end;
  12877. btCurrency: begin MinVal:=MinSafeIntCurrency; MaxVal:=MaxSafeIntCurrency; end;
  12878. else
  12879. Result:=false;
  12880. end;
  12881. end;
  12882. function TPasResolver.GetIntegerBaseType(Precision: word; Signed: boolean;
  12883. ErrorEl: TPasElement): TResolverBaseType;
  12884. begin
  12885. if Precision<=8 then
  12886. begin
  12887. if Signed then
  12888. Result:=btShortInt
  12889. else
  12890. Result:=btByte;
  12891. if BaseTypes[Result]<>nil then exit;
  12892. end;
  12893. if Precision<=16 then
  12894. begin
  12895. if Signed then
  12896. Result:=btSmallInt
  12897. else
  12898. Result:=btWord;
  12899. if BaseTypes[Result]<>nil then exit;
  12900. end;
  12901. if (Precision<=22) and (not Signed) and (BaseTypes[btUIntSingle]<>nil) then
  12902. exit(btUIntSingle);
  12903. if (Precision<=23) and Signed and (BaseTypes[btIntSingle]<>nil) then
  12904. exit(btIntSingle);
  12905. if Precision<=32 then
  12906. begin
  12907. if Signed then
  12908. Result:=btLongint
  12909. else
  12910. Result:=btLongWord;
  12911. if BaseTypes[Result]<>nil then exit;
  12912. end;
  12913. if (Precision<=52) and (not Signed) and (BaseTypes[btUIntDouble]<>nil) then
  12914. exit(btUIntDouble);
  12915. if (Precision<=53) and Signed and (BaseTypes[btIntDouble]<>nil) then
  12916. exit(btIntDouble);
  12917. if Precision<=64 then
  12918. begin
  12919. if Signed then
  12920. Result:=btInt64
  12921. else
  12922. Result:=btQWord;
  12923. if BaseTypes[Result]<>nil then exit;
  12924. end;
  12925. RaiseRangeCheck(20170420100336,ErrorEl);
  12926. end;
  12927. function TPasResolver.GetCombinedChar(const Char1, Char2: TPasResolverResult;
  12928. ErrorEl: TPasElement): TResolverBaseType;
  12929. var
  12930. bt1, bt2: TResolverBaseType;
  12931. begin
  12932. bt1:=GetActualBaseType(Char1.BaseType);
  12933. bt2:=GetActualBaseType(Char2.BaseType);
  12934. if bt1=bt2 then exit(bt1);
  12935. if not (bt1 in btAllChars) then
  12936. RaiseInternalError(20170420103128);
  12937. Result:=btWideChar;
  12938. if Result=BaseTypeChar then
  12939. Result:=btChar;
  12940. if ErrorEl=nil then ;
  12941. end;
  12942. function TPasResolver.GetCombinedString(const Str1, Str2: TPasResolverResult;
  12943. ErrorEl: TPasElement): TResolverBaseType;
  12944. var
  12945. bt1, bt2: TResolverBaseType;
  12946. begin
  12947. bt1:=GetActualBaseType(Str1.BaseType);
  12948. bt2:=GetActualBaseType(Str2.BaseType);
  12949. if bt1=bt2 then exit(bt1);
  12950. case bt1 of
  12951. btChar,btAnsiChar:
  12952. case bt2 of
  12953. btChar: Result:=btChar;
  12954. btWideChar: Result:=btWideChar;
  12955. else Result:=bt2;
  12956. end;
  12957. btWideChar:
  12958. case bt2 of
  12959. btAnsiChar: Result:=btWideChar;
  12960. btWideString: Result:=btWideString;
  12961. btString,btShortString,btAnsiString,btRawByteString,btUnicodeString: Result:=btUnicodeString;
  12962. else RaiseNotYetImplemented(20170420103808,ErrorEl);
  12963. end;
  12964. btShortString:
  12965. case bt2 of
  12966. btChar,btAnsiChar: Result:=btShortString;
  12967. btString,btAnsiString: Result:=btAnsiString;
  12968. btRawByteString: Result:=btRawByteString;
  12969. btWideChar,btUnicodeString: Result:=btUnicodeString;
  12970. btWideString: Result:=btWideString;
  12971. else RaiseNotYetImplemented(20170420120937,ErrorEl);
  12972. end;
  12973. btString,btAnsiString:
  12974. case bt2 of
  12975. btChar,btAnsiChar,btString,btShortString,btRawByteString: Result:=btAnsiString;
  12976. btWideChar,btUnicodeString: Result:=btUnicodeString;
  12977. btWideString: Result:=btWideString;
  12978. else RaiseNotYetImplemented(20170420121201,ErrorEl);
  12979. end;
  12980. btRawByteString:
  12981. case bt2 of
  12982. btChar,btAnsiChar,btRawByteString,btShortString: Result:=btRawByteString;
  12983. btString,btAnsiString: Result:=btAnsiString;
  12984. btWideChar,btUnicodeString: Result:=btUnicodeString;
  12985. btWideString: Result:=btWideString;
  12986. else RaiseNotYetImplemented(20170420121352,ErrorEl);
  12987. end;
  12988. btWideString:
  12989. case bt2 of
  12990. btChar,btAnsiChar,btWideChar,btShortString,btWideString: Result:=btWideString;
  12991. btString,btAnsiString,btUnicodeString: Result:=btUnicodeString;
  12992. else RaiseNotYetImplemented(20170420121532,ErrorEl);
  12993. end;
  12994. btUnicodeString:
  12995. Result:=btUnicodeString;
  12996. else
  12997. RaiseNotYetImplemented(20170420103153,ErrorEl);
  12998. end;
  12999. if Result=BaseTypeChar then
  13000. Result:=btChar
  13001. else if Result=BaseTypeString then
  13002. Result:=btString;
  13003. end;
  13004. function TPasResolver.CheckSrcIsADstType(const ResolvedSrcType,
  13005. ResolvedDestType: TPasResolverResult; ErrorEl: TPasElement): integer;
  13006. // finds distance between classes SrcType and DestType
  13007. begin
  13008. Result:=CheckClassIsClass(ResolvedSrcType.TypeEl,ResolvedDestType.TypeEl,ErrorEl);
  13009. end;
  13010. function TPasResolver.CheckClassIsClass(SrcType, DestType: TPasType;
  13011. ErrorEl: TPasElement): integer;
  13012. // check if Src is equal or descends from Dest
  13013. var
  13014. ClassEl: TPasClassType;
  13015. begin
  13016. {$IFDEF VerbosePasResolver}
  13017. writeln('TPasResolver.CheckClassIsClass SrcType=',GetObjName(SrcType),' DestType=',GetObjName(DestType));
  13018. {$ENDIF}
  13019. if DestType=nil then exit(cIncompatible);
  13020. // skip Dest alias
  13021. while (DestType.ClassType=TPasAliasType) do
  13022. DestType:=TPasAliasType(DestType).DestType;
  13023. Result:=cExact;
  13024. while SrcType<>nil do
  13025. begin
  13026. {$IFDEF VerbosePasResolver}
  13027. writeln(' Step=',Result,' SrcType=',GetObjName(SrcType),' DestType=',GetObjName(DestType));
  13028. {$ENDIF}
  13029. if SrcType=DestType then
  13030. exit
  13031. else if SrcType.ClassType=TPasAliasType then
  13032. // alias -> skip
  13033. SrcType:=TPasAliasType(SrcType).DestType
  13034. else if SrcType.ClassType=TPasTypeAliasType then
  13035. begin
  13036. // type alias -> increases distance
  13037. SrcType:=TPasAliasType(SrcType).DestType;
  13038. inc(Result);
  13039. end
  13040. else if SrcType.ClassType=TPasClassType then
  13041. begin
  13042. ClassEl:=TPasClassType(SrcType);
  13043. if ClassEl.IsForward then
  13044. // class forward -> skip
  13045. SrcType:=(ClassEl.CustomData as TResolvedReference).Declaration as TPasType
  13046. else
  13047. begin
  13048. // class ancestor -> increase distance
  13049. SrcType:=(ClassEl.CustomData as TPasClassScope).DirectAncestor;
  13050. inc(Result);
  13051. end;
  13052. end
  13053. else
  13054. exit(cIncompatible);
  13055. end;
  13056. if ErrorEl=nil then ;
  13057. Result:=cIncompatible;
  13058. end;
  13059. function TPasResolver.CheckClassesAreRelated(TypeA, TypeB: TPasType;
  13060. ErrorEl: TPasElement): integer;
  13061. begin
  13062. Result:=CheckClassIsClass(TypeA,TypeB,ErrorEl);
  13063. if Result<>cIncompatible then exit;
  13064. Result:=CheckClassIsClass(TypeB,TypeA,ErrorEl);
  13065. end;
  13066. end.