12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381 |
- %
- % $Id$
- % This file is part of the FPC documentation.
- % Copyright (C) 1997, by Michael Van Canneyt
- %
- % The FPC documentation is free text; you can redistribute it and/or
- % modify it under the terms of the GNU Library General Public License as
- % published by the Free Software Foundation; either version 2 of the
- % License, or (at your option) any later version.
- %
- % The FPC Documentation is distributed in the hope that it will be useful,
- % but WITHOUT ANY WARRANTY; without even the implied warranty of
- % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- % Library General Public License for more details.
- %
- % You should have received a copy of the GNU Library General Public
- % License along with the FPC documentation; see the file COPYING.LIB. If not,
- % write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- % Boston, MA 02111-1307, USA.
- %
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Preamble.
- \input{preamble.inc}
- \begin{latexonly}
- \ifpdf
- \pdfinfo{/Author(Michael Van Canneyt)
- /Title(Free Pascal Language Reference Guide)
- /Subject(Free Pascal Reference guide)
- /Keywords(Free Pascal, Language)
- }
- \fi
- \end{latexonly}
- %
- % Settings
- %
- \makeindex
- %
- % Syntax style
- %
- \usepackage{syntax}
- \input{syntax/diagram.tex}
- %
- % Start of document.
- %
- \begin{document}
- \renewcommand{\hline}{\xspace}
- \title{Free Pascal :\\ Reference guide.}
- \docdescription{Reference guide for Free Pascal, version \fpcversion}
- \docversion{2.0}
- \input{date.inc}
- \author{Micha\"el Van Canneyt}
- \maketitle
- \tableofcontents
- \newpage
- \listoftables
- \newpage
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Introduction
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % About this guide
- \section*{About this guide}
- This document serves as the reference for the Pascal langauge as implemented
- by the \fpc compiler. It describes all Pascal constructs supported by
- \fpc, and lists all supported data types. It does not, however, give a
- detailed explanation of the pascal language. The aim is to list which
- Pascal constructs are supported, and to show where the \fpc implementation
- differs from the Turbo Pascal or Delphi implementations.
- Earlier versions of this document also contained the reference documentation
- of the \file{system} unit and \file{objpas} unit. This has been moved to the
- RTL reference guide.
- \subsection*{Notations}
- Throughout this document, we will refer to functions, types and variables
- with \var{typewriter} font. Functions and procedures have their own
- subsections, and for each function or procedure we have the following
- topics:
- \begin{description}
- \item [Declaration] The exact declaration of the function.
- \item [Description] What does the procedure exactly do ?
- \item [Errors] What errors can occur.
- \item [See Also] Cross references to other related functions/commands.
- \end{description}
- The cross-references come in two flavours:
- \begin{itemize}
- \item References to other functions in this manual. In the printed copy, a
- number will appear after this reference. It refers to the page where this
- function is explained. In the on-line help pages, this is a hyperlink,
- which can be clicked to jump to the declaration.
- \item References to Unix manual pages. (For linux and unix related things only) they
- are printed in \var{typewriter} font, and the number after it is the Unix
- manual section.
- \end{itemize}
- \subsection*{Syntax diagrams}
- All elements of the pascal language are explained in syntax diagrams.
- Syntax diagrams are like flow charts. Reading a syntax diagram means getting
- from the left side to the right side, following the arrows.
- When the right side of a syntax diagram is reached, and it ends with a single
- arrow, this means the syntax diagram is continued on the next line. If
- the line ends on 2 arrows pointing to each other, then the diagram is
- ended.
- Syntactical elements are written like this
- \begin{mysyntdiag}
- \synt{syntactical\ elements\ are\ like\ this}
- \end{mysyntdiag}
- Keywords which must be typed exactly as in the diagram:
- \begin{mysyntdiag}
- \lit*{keywords\ are\ like\ this}
- \end{mysyntdiag}
- When something can be repeated, there is an arrow around it:
- \begin{mysyntdiag}
- \begin{rep}[b] \synt{this\ can\ be\ repeated} \\ \end{rep}
- \end{mysyntdiag}
- When there are different possibilities, they are listed in columns:
- \begin{mysyntdiag}
- \begin{stack}
- \synt{First\ possibility} \\
- \synt{Second\ possibility}
- \end{stack}
- \end{mysyntdiag}
- Note, that one of the possibilities can be empty:
- \begin{mysyntdiag}
- \begin{stack}\\
- \synt{First\ possibility} \\
- \synt{Second\ possibility}
- \end{stack}
- \end{mysyntdiag}
- This means that both the first or second possibility are optional.
- Of course, all these elements can be combined and nested.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The Pascal language
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Pascal Tokens}
- In this chapter we describe all the pascal reserved words, as well as the
- various ways to denote strings, numbers, identifiers etc.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Symbols
- \section{Symbols}
- Free Pascal allows all characters, digits and some special ASCII symbols
- in a Pascal source file.
- \input{syntax/symbol.syn}
- The following characters have a special meaning:
- \begin{verbatim}
- + - * / = < > [ ] . , ( ) : ^ @ { } $ #
- \end{verbatim}
- and the following character pairs too:
- \begin{verbatim}
- <= >= := += -= *= /= (* *) (. .) //
- \end{verbatim}
- When used in a range specifier, the character pair \var{(.} is equivalent to
- the left square bracket \var{[}. Likewise, the character pair \var{.)} is
- equivalent to the right square bracket \var{]}.
- When used for comment delimiters, the character pair \var{(*} is equivalent
- to the left brace \var{\{} and the character pair \var{*)} is equivalent
- to the right brace \var{\}}.
- These character pairs retain their normal meaning in string expressions.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Comments
- \section{Comments}
- \fpc supports the use of nested comments. The following constructs are valid
- comments:
- \begin{verbatim}
- (* This is an old style comment *)
- { This is a Turbo Pascal comment }
- // This is a Delphi comment. All is ignored till the end of the line.
- \end{verbatim}
- The following are valid ways of nesting comments:
- \begin{verbatim}
- { Comment 1 (* comment 2 *) }
- (* Comment 1 { comment 2 } *)
- { comment 1 // Comment 2 }
- (* comment 1 // Comment 2 *)
- // comment 1 (* comment 2 *)
- // comment 1 { comment 2 }
- \end{verbatim}
- The last two comments {\em must} be on one line. The following two will give
- errors:
- \begin{verbatim}
- // Valid comment { No longer valid comment !!
- }
- \end{verbatim}
- and
- \begin{verbatim}
- // Valid comment (* No longer valid comment !!
- *)
- \end{verbatim}
- The compiler will react with a 'invalid character' error when it encounters
- such constructs, regardless of the \var{-So} switch.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Reserved words
- \section{Reserved words}
- Reserved words are part of the Pascal language, and cannot be redefined.
- They will be denoted as {\sffamily\bfseries this} throughout the syntax
- diagrams. Reserved words can be typed regardless of case, i.e. Pascal is
- case insensitive.
- We make a distinction between Turbo Pascal and Delphi reserved words, since
- with the \var{-So} switch, only the Turbo Pascal reserved words are
- recognised, and the Delphi ones can be redefined. By default, \fpc
- recognises the Delphi reserved words.
- \subsection{Turbo Pascal reserved words}
- The following keywords exist in Turbo Pascal mode
- \begin{multicols}{4}
- \begin{verbatim}
- absolute
- and
- array
- asm
- begin
- break
- case
- const
- constructor
- continue
- destructor
- div
- do
- downto
- else
- end
- file
- for
- function
- goto
- if
- implementation
- in
- inherited
- inline
- interface
- label
- mod
- nil
- not
- object
- of
- on
- operator
- or
- packed
- procedure
- program
- record
- repeat
- self
- set
- shl
- shr
- string
- then
- to
- type
- unit
- until
- uses
- var
- while
- with
- xor
- \end{verbatim}
- \end{multicols}
- \subsection{Delphi reserved words}
- The Delphi (II) reserved words are the same as the pascal ones, plus the
- following ones:
- \begin{multicols}{4}
- \begin{verbatim}
- as
- class
- except
- exports
- finalization
- finally
- initialization
- is
- library
- on
- property
- raise
- threadvar
- try
- \end{verbatim}
- \end{multicols}
- \subsection{\fpc reserved words}
- On top of the Turbo Pascal and Delphi reserved words, \fpc also considers
- the following as reserved words:
- \begin{multicols}{4}
- \begin{verbatim}
- dispose
- exit
- false
- new
- true
- \end{verbatim}
- \end{multicols}
- \subsection{Modifiers}
- The following is a list of all modifiers. They are not exactly reserved
- words in the sense that they can be used as identifiers, but in specific
- places, they have a special meaning for the compiler.
- \begin{multicols}{4}
- \begin{verbatim}
- absolute
- abstract
- alias
- assembler
- cdecl
- default
- export
- external
- far
- far16
- forward
- fpccall
- index
- name
- near
- override
- pascal
- popstack
- private
- protected
- public
- published
- read
- register
- safecall
- saveregisters
- softfloat
- stdcall
- virtual
- write
- \end{verbatim}
- \end{multicols}
- \begin{remark}
- Predefined types such as \var{Byte}, \var{Boolean} and constants
- such as \var{maxint} are {\em not} reserved words. They are
- identifiers, declared in the system unit. This means that these types
- can be redefined in other units. The programmer is, however, not
- encouraged to do this, as it will cause a lot of confusion.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Identifiers
- \section{Identifiers}
- Identifiers denote constants, types, variables, procedures and functions,
- units, and programs. All names of things that are defined are identifiers.
- An identifier consists of 255 significant characters (letters, digits and
- the underscore character), from which the first must be an alphanumeric
- character, or an underscore (\var{\_})
- The following diagram gives the basic syntax for identifiers.
- \input{syntax/identifier.syn}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Numbers
- \section{Numbers}
- Numbers are by default denoted in decimal notation.
- Real (or decimal) numbers are written using engineering or scientific
- notation (e.g. \var{0.314E1}).
- For integer type constants, \fpc supports 4 formats:
- \begin{enumerate}
- \item Normal, decimal format (base 10). This is the standard format.
- \item Hexadecimal format (base 16), in the same way as Turbo Pascal does.
- To specify a constant value in hexadecimal format, prepend it with a dollar
- sign (\var{\$}). Thus, the hexadecimal \var{\$FF} equals 255 decimal.
- Note that case is insignificant when using hexadecimal constants.
- \item As of version 1.0.7, Octal format (base 8) is also supported.
- To specify a constant in octal format, prepend it with a ampersand (\&).
- For instance 15 is specified in octal notation as \var{\&17}.
- \item Binary notation (base 2). A binary number can be specified
- by preceding it with a percent sign (\var{\%}). Thus, \var{255} can be
- specified in binary notation as \var{\%11111111}.
- \end{enumerate}
- The following diagrams show the syntax for numbers.
- \input{syntax/numbers.syn}
- \begin{remark}
- It is to note that all decimal constants which do no fit within
- the -2147483648..2147483647 range, are silently and automatically
- parsed as 64-bit integer constants as of version 1.9.0. Earliers
- versions would convert it to a real-typed constant.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Labels
- \section{Labels}
- Labels can be digit sequences or identifiers.
- \input{syntax/label.syn}
- \begin{remark}
- Note that the \var{-Sg} switch must be specified before labels can be used.
- By default, \fpc doesn't support \var{label} and \var{goto} statements.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Character strings
- \section{Character strings}
- A character string (or string for short) is a sequence of zero or more
- characters from the ASCII character set, enclosed by single quotes, and on 1
- line of the program source.
- A character set with nothing between the quotes (\var{'{}'}) is an empty
- string.
- \input{syntax/string.syn}
- \chapter{Constants}
- Just as in Turbo Pascal, \fpc supports both normal and typed constants.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Ordinary constants
- \section{Ordinary constants}
- Ordinary constants declarations are not different from the Turbo Pascal or
- Delphi implementation.
- \input{syntax/const.syn}
- The compiler must be able to evaluate the expression in a constant
- declaration at compile time. This means that most of the functions
- in the Run-Time library cannot be used in a constant declaration.
- Operators such as \var{+, -, *, /, not, and, or, div, mod, ord, chr,
- sizeof, pi, int, trunc, round, frac, odd} can be used, however. For more
- information on expressions, see \seec{Expressions}.
- Only constants of the following types can be declared: \var{Ordinal types},
- \var{Real types}, \var{Char}, and \var{String}.
- The following are all valid constant declarations:
- \begin{verbatim}
- Const
- e = 2.7182818; { Real type constant. }
- a = 2; { Ordinal (Integer) type constant. }
- c = '4'; { Character type constant. }
- s = 'This is a constant string'; {String type constant.}
- s = chr(32)
- ls = SizeOf(Longint);
- \end{verbatim}
- Assigning a value to an ordinary constant is not permitted.
- Thus, given the previous declaration, the following will result
- in a compiler error:
- \begin{verbatim}
- s := 'some other string';
- \end{verbatim}
- Prior to version 1.9, \fpc did not correctly support 64-bit constants. As
- of version 1.9, 64-bits constants can be specified.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Typed constants
- \section{Typed constants}
- Typed constants serve to provide a program with initialised variables.
- Contrary to ordinary constants, they may be assigned to at run-time.
- The difference with normal variables is that their value is initialised
- when the program starts, whereas normal variables must be initialised
- explicitly.
- \input{syntax/tconst.syn}
- Given the declaration:
- \begin{verbatim}
- Const
- S : String = 'This is a typed constant string';
- \end{verbatim}
- The following is a valid assignment:
- \begin{verbatim}
- S := 'Result : '+Func;
- \end{verbatim}
- Where \var{Func} is a function that returns a \var{String}.
- Typed constants are often used to initialize arrays and records. For arrays,
- the initial elements must be specified, surrounded by round brackets, and
- separated by commas. The number of elements must be exactly the same as
- the number of elements in the declaration of the type.
- As an example:
- \begin{verbatim}
- Const
- tt : array [1..3] of string[20] = ('ikke', 'gij', 'hij');
- ti : array [1..3] of Longint = (1,2,3);
- \end{verbatim}
- For constant records, each element of the record should be specified, in
- the form \var{Field : Value}, separated by commas, and surrounded by round
- brackets.
- As an example:
- \begin{verbatim}
- Type
- Point = record
- X,Y : Real
- end;
- Const
- Origin : Point = (X:0.0; Y:0.0);
- \end{verbatim}
- The order of the fields in a constant record needs to be the same as in the type declaration,
- otherwise a compile-time error will occur.
- \begin{remark}
- It should be stressed that typed constants are initialized at program start.
- This is also true for {\em local} typed constants. Local typed constants are
- also initialized at program start. If their value was changed during previous
- invocations of the function, they will retain their changed value, i.e. they
- are not initialized each time the function is invoked.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % resource strings
- \section{Resource strings}
- \label{se:resourcestring}
- A special kind of constant declaration part is the \var{Resourestring}
- part. This part is like a \var{Const} section, but it only allows
- to declare constant of type string. This part is only available in the
- \var{Delphi} or \var{objfpc} mode.
- The following is an example of a resourcestring definition:
- \begin{verbatim}
- Resourcestring
- FileMenu = '&File...';
- EditMenu = '&Edit...';
- \end{verbatim}
- All string constants defined in the resourcestring section are stored
- in special tables, allowing to manipulate the values of the strings
- at runtime with some special mechanisms.
- Semantically, the strings are like constants; Values can not be assigned to
- them, except through the special mechanisms in the objpas unit. However,
- they can be used in assignments or expressions as normal constants.
- The main use of the resourcestring section is to provide an easy means
- of internationalization.
- More on the subject of resourcestrings can be found in the \progref, and
- in the chapter on the \file{objpas} later in this manual.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Types
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Types}
- All variables have a type. \fpc supports the same basic types as Turbo
- Pascal, with some extra types from Delphi.
- The programmer can declare his own types, which is in essence defining an identifier
- that can be used to denote this custom type when declaring variables further
- in the source code.
- \input{syntax/typedecl.syn}
- There are 7 major type classes :
- \input{syntax/type.syn}
- The last class, {\sffamily type identifier}, is just a means to give another
- name to a type. This presents a way to make types platform independent, by
- only using these types, and then defining these types for each platform
- individually. The programmer that uses these units doesn't have to worry
- about type size and so on. It also allows to use shortcut names for
- fully qualified type names. e.g. define \var{system.longint} as
- \var{Olongint} and then redefine \var{longint}.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Base types
- \section{Base types}
- The base or simple types of \fpc are the Delphi types.
- We will discuss each separate.
- \input{syntax/typesim.syn}
- \subsection{Ordinal types}
- With the exception of \var{int64}, \var{qword} and Real types,
- all base types are ordinal types. Ordinal types have the following
- characteristics:
- \begin{enumerate}
- \item Ordinal types are countable and ordered, i.e. it is, in principle,
- possible to start counting them one bye one, in a specified order.
- This property allows the operation of functions as \seep{Inc}, \seef{Ord},
- \seep{Dec}
- on ordinal types to be defined.
- \item Ordinal values have a smallest possible value. Trying to apply the
- \seef{Pred} function on the smallest possible value will generate a range
- check error if range checking is enabled.
- \item Ordinal values have a largest possible value. Trying to apply the
- \seef{Succ} function on the largest possible value will generate a range
- check error if range checking is enabled.
- \end{enumerate}
- \subsubsection{Integers}
- A list of pre-defined integer types is presented in \seet{integerstyp}
- %
- \begin{table}[ht]
- \caption{Predefined integer types}
- \label{tab:integerstyp}
- \begin{center}
- \begin{tabular}{l}
- %\begin{FPCltable}{l}{Predefined integer types}{integerstyp}
- Name\\ \hline
- Integer \\
- Shortint \\
- SmallInt \\
- Longint \\
- Longword \\
- Int64 \\
- Byte \\
- Word \\
- Cardinal \\
- QWord \\
- Boolean \\
- ByteBool \\
- LongBool \\
- Char \\ \hline
- \end{tabular}
- \end{center}
- \end{table}
- %\end{FPCltable}
- The integer types, and their ranges and sizes, that are predefined in
- \fpc are listed in \seet{integersranges}. It is to note that
- the \var{qword} and \var{int64} types are not true ordinals, so
- some pascal constructs will not work with these two integer types.
- \begin{FPCltable}{lcr}{Predefined integer types}{integersranges}
- Type & Range & Size in bytes \\ \hline
- Byte & 0 .. 255 & 1 \\
- Shortint & -128 .. 127 & 1\\
- Smallint & -32768 .. 32767 & 2\\
- Word & 0 .. 65535 & 2 \\
- Integer & either smallint, longint or int64 & size 2,4 or 8 \\
- Cardinal & either word, longword or qword & size 2,4 or 8 \\
- Longint & -2147483648 .. 2147483647 & 4\\
- Longword & 0..4294967295 & 4 \\
- Int64 & -9223372036854775808 .. 9223372036854775807 & 8 \\
- QWord & 0 .. 18446744073709551615 & 8 \\ \hline
- \end{FPCltable}
- The \var{integer} type maps to the smallint type in the default
- \fpc mode. It maps to either a longint or int64 in either Delphi or ObjFPC
- mode. The \var{cardinal} type is currently always mapped to the
- longword type. The definition of the \var{cardinal} and \var{integer}
- types may change from one architecture to another and from one
- compiler mode to another. They usually have the same size as the
- underlying target architecture.
- % This IS NOT TRUE, this is a 32-bit compiler, so the integer type
- % will always be the same independently the CPU type.
- %This is summarized in \seet{integer32type} for 32-bit processors
- %(such as Intel 80x86, Motorola 680x0, PowerPC 32-bit, SPARC v7, MIPS32), and
- %in \seet{integer64type} for 64-bit processors (such as Alpha AXP,
- %SPARC v9 or later, Intel Itanium, MIPS64).
- %\begin{FPCltable}{lcr}{\var{Integer} type mapping for 32-bit processors}{integer32type}
- %Compiler mode & Range & Size in bytes \\ \hline
- %<default> & -32768 .. 32767 & 2\\
- %tp & -32768 .. 32767 & 2\\
- %Delphi & -2147483648 .. 2147483647 & 4\\
- %ObjFPC & -2147483648 .. 2147483647 & 4\\
- %\end{FPCltable}
- %\begin{FPCltable}{lcr}{\var{Integer} type mapping for 64-bit processors}{integer64type}
- %Compiler mode & Range & Size in bytes \\ \hline
- %<default> & -32768 .. 32767 & 2\\
- %tp & -32768 .. 32767 & 2\\
- %Delphi & -9223372036854775808 .. 9223372036854775807 & 8 \\
- %ObjFPC & -9223372036854775808 .. 9223372036854775807 & 8 \\
- %\end{FPCltable}
- \fpc does automatic type conversion in expressions where different kinds of
- integer types are used.
- \subsubsection{Boolean types}
- \fpc supports the \var{Boolean} type, with its two pre-defined possible
- values \var{True} and \var{False}. It also supports the \var{ByteBool},
- \var{WordBool} and \var{LongBool} types. These are the only two values that can be
- assigned to a \var{Boolean} type. Of course, any expression that resolves
- to a \var{boolean} value, can also be assigned to a boolean type.
- \begin{FPCltable}{lll}{Boolean types}{booleantypes}
- Name & Size & Ord(True) \\ \hline
- Boolean & 1 & 1 \\
- ByteBool & 1 & Any nonzero value \\
- WordBool & 2 & Any nonzero value \\
- LongBool & 4 & Any nonzero value \\ \hline
- \end{FPCltable}
- Assuming \var{B} to be of type \var{Boolean}, the following are valid
- assignments:
- \begin{verbatim}
- B := True;
- B := False;
- B := 1<>2; { Results in B := True }
- \end{verbatim}
- Boolean expressions are also used in conditions.
- \begin{remark}
- In \fpc, boolean expressions are always evaluated in such a
- way that when the result is known, the rest of the expression will no longer
- be evaluated (Called short-cut evaluation). In the following example, the function \var{Func} will never
- be called, which may have strange side-effects.
- \begin{verbatim}
- ...
- B := False;
- A := B and Func;
- \end{verbatim}
- Here \var{Func} is a function which returns a \var{Boolean} type.
- \end{remark}
- \subsubsection{Enumeration types}
- Enumeration types are supported in \fpc. On top of the Turbo Pascal
- implementation, \fpc allows also a C-style extension of the
- enumeration type, where a value is assigned to a particular element of
- the enumeration list.
- \input{syntax/typeenum.syn}
- (see \seec{Expressions} for how to use expressions)
- When using assigned enumerated types, the assigned elements must be in
- ascending numerical order in the list, or the compiler will complain.
- The expressions used in assigned enumerated elements must be known at
- compile time.
- So the following is a correct enumerated type declaration:
- \begin{verbatim}
- Type
- Direction = ( North, East, South, West );
- \end{verbatim}
- The C style enumeration type looks as follows:
- \begin{verbatim}
- Type
- EnumType = (one, two, three, forty := 40,fortyone);
- \end{verbatim}
- As a result, the ordinal number of \var{forty} is \var{40}, and not \var{3},
- as it would be when the \var{':= 40'} wasn't present.
- The ordinal value of \var{fortyone} is then {41}, and not \var{4}, as it
- would be when the assignment wasn't present. After an assignment in an
- enumerated definition the compiler adds 1 to the assigned value to assign to
- the next enumerated value.
- When specifying such an enumeration type, it is important to keep in mind
- that the enumerated elements should be kept in ascending order. The
- following will produce a compiler error:
- \begin{verbatim}
- Type
- EnumType = (one, two, three, forty := 40, thirty := 30);
- \end{verbatim}
- It is necessary to keep \var{forty} and \var{thirty} in the correct order.
- When using enumeration types it is important to keep the following points
- in mind:
- \begin{enumerate}
- \item The \var{Pred} and \var{Succ} functions cannot be used on
- this kind of enumeration types. Trying to do this anyhow will result in a
- compiler error.
- \item Enumeration types stored using a default size. This behaviour can be changed
- with the \var{\{\$PACKENUM n\}} compiler directive, which
- tells the compiler the minimal number of bytes to be used for enumeration
- types.
- For instance
- \begin{verbatim}
- Type
- {$PACKENUM 4}
- LargeEnum = ( BigOne, BigTwo, BigThree );
- {$PACKENUM 1}
- SmallEnum = ( one, two, three );
- Var S : SmallEnum;
- L : LargeEnum;
- begin
- WriteLn ('Small enum : ',SizeOf(S));
- WriteLn ('Large enum : ',SizeOf(L));
- end.
- \end{verbatim}
- will, when run, print the following:
- \begin{verbatim}
- Small enum : 1
- Large enum : 4
- \end{verbatim}
- \end{enumerate}
- More information can be found in the \progref, in the compiler directives
- section.
- \subsubsection{Subrange types}
- A subrange type is a range of values from an ordinal type (the {\em host}
- type). To define a subrange type, one must specify it's limiting values: the
- highest and lowest value of the type.
- \input{syntax/typesubr.syn}
- Some of the predefined \var{integer} types are defined as subrange types:
- \begin{verbatim}
- Type
- Longint = $80000000..$7fffffff;
- Integer = -32768..32767;
- shortint = -128..127;
- byte = 0..255;
- Word = 0..65535;
- \end{verbatim}
- Subrange types of enumeration types can also be defined:
- \begin{verbatim}
- Type
- Days = (monday,tuesday,wednesday,thursday,friday,
- saturday,sunday);
- WorkDays = monday .. friday;
- WeekEnd = Saturday .. Sunday;
- \end{verbatim}
- \subsection{Real types}
- \fpc uses the math coprocessor (or emulation) for all its floating-point
- calculations. The Real native type is processor dependant,
- but it is either Single or Double. Only the IEEE floating point types are
- supported, and these depend on the target processor and emulation options.
- The true Turbo Pascal compatible types are listed in
- \seet{Reals}.
- \begin{FPCltable}{lccr}{Supported Real types}{Reals}
- Type & Range & Significant digits & Size \\ \hline
- Real & platform dependant & ??? & 4 or 8 \\
- Single & 1.5E-45 .. 3.4E38 & 7-8 & 4 \\
- Double & 5.0E-324 .. 1.7E308 & 15-16 & 8 \\
- Extended & 1.9E-4951 .. 1.1E4932 & 19-20 & 10\\
- Comp & -2E64+1 .. 2E63-1 & 19-20 & 8 \\
- \end{FPCltable}
- The \var{Comp} type is, in effect, a 64-bit integer and is not available
- on all target platforms. To get more information on the supported types
- for each platform, refer to the \progref.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Character types
- \section{Character types}
- \subsection{Char}
- \fpc supports the type \var{Char}. A \var{Char} is exactly 1 byte in
- size, and contains one character.
- A character constant can be specified by enclosing the character in single
- quotes, as follows : 'a' or 'A' are both character constants.
- A character can also be specified by its ASCII
- value, by preceding the ASCII value with the number symbol (\#). For example
- specifying \var{\#65} would be the same as \var{'A'}.
- Also, the caret character (\verb+^+) can be used in combination with a letter to
- specify a character with ASCII value less than 27. Thus \verb+^G+ equals
- \var{\#7} (G is the seventh letter in the alphabet.)
- When the single quote character must be represented, it should be typed
- two times successively, thus \var{''''} represents the single quote character.
- \subsection{Strings}
- \fpc supports the \var{String} type as it is defined in Turbo Pascal
- (A sequence of characters with a specified length) and it
- supports ansistrings as in Delphi.
- To declare a variable as a string, use the following type specification:
- \input{syntax/sstring.syn}
- The meaning of a string declaration statement is interpreted differently
- depending on the \var{\{\$H\}} switch. The above declaration can declare an
- ansistrng or a short string.
- Whatever the actual type, ansistrings and short strings can be used
- interchangeably. The compiler always takes care of the necessary type
- conversions. Note, however, that the result of an expression that contains
- ansistrings and short strings will always be an ansistring.
- \subsection{Short strings}
- A string declaration declares a short string in the following cases:
- \begin{enumerate}
- \item If the switch is off: \var{\{\$H-\}}, the string declaration
- will always be a short string declaration.
- \item If the switch is on \var{\{\$H+\}}, and there is a length
- specifier, the declaration is a short string declaration.
- \end{enumerate}
- The predefined type \var{ShortString} is defined as a string of length 255:
- \begin{verbatim}
- ShortString = String[255];
- \end{verbatim}
- If the size of the string is not specified, \var{255} is taken as a
- default. The length of the string can be obtained with the \seef{Length}
- standard runtime routine.
- For example in
- \begin{verbatim}
- {$H-}
- Type
- NameString = String[10];
- StreetString = String;
- \end{verbatim}
- \var{NameString} can contain a maximum of 10 characters. While
- \var{StreetString} can contain up to 255 characters.
- \subsection{Ansistrings}
- Ansistrings are strings that have no length limit. They are reference
- counted and null terminated. Internally, an ansistring is treated as
- a pointer. This is all handled transparantly, i.e. they can be manipulated
- as a normal short string. Ansistrings can be defined using the predefined
- \var{AnsiString} type.
- If the \var{\{\$H\}} switch is on, then a string definition using the
- regular \var{String} keyword and that doesn't contain a length specifier,
- will be regarded as an ansistring as well. If a length specifier is present,
- a short string will be used, regardless of the \var{\{\$H\}} setting.
- If the string is empty (\var{''}), then the internal pointer representation
- of the string pointer is \var{Nil}. If the string is not empty, then the
- pointer points to a structure in heap memory.
- The internal representation as a pointer, and the automatic null-termination
- make it possible to typecast an ansistring to a pchar. If the string is empty
- (so the pointer is nil) then the compiler makes sure that the typecasted
- pchar will point to a null byte.
- Assigning one ansistring to another doesn't involve moving the actual
- string. A statement
- \begin{verbatim}
- S2:=S1;
- \end{verbatim}
- results in the reference count of \var{S2} being decreased by one,
- The referece count of \var{S1} is increased by one, and finally \var{S1}
- (as a pointer) is copied to \var{S2}. This is a significant speed-up in
- the code.
- If the reference count reaches zero, then the memory occupied by the
- string is deallocated automatically, so no memory leaks arise.
- When an ansistring is declared, the \fpc compiler initially
- allocates just memory for a pointer, not more. This pointer is guaranteed
- to be nil, meaning that the string is initially empty. This is
- true for local and global ansistrings or anstrings that are part of a
- structure (arrays, records or objects).
- This does introduce an overhead. For instance, declaring
- \begin{verbatim}
- Var
- A : Array[1..100000] of string;
- \end{verbatim}
- Will copy 100,000 times \var{nil} into \var{A}. When \var{A} goes out of scope, then
- the reference count of the 100,000 strings will be decreased by 1 for each
- of these strings. All this happens
- invisibly for the programmer, but when considering performance issues,
- this is important.
- Memory will be allocated only when the string is assigned a value.
- If the string goes out of scope, then its reference count is automatically
- decreased by 1. If the reference count reaches zero, the memory reserved for
- the string is released.
- If a value is assigned to a character of a string that has a reference count
- greater than 1, such as in the following
- statements:
- \begin{verbatim}
- S:=T; { reference count for S and T is now 2 }
- S[I]:='@';
- \end{verbatim}
- then a copy of the string is created before the assignment. This is known
- as {\em copy-on-write} semantics.
- The \seef{Length} function must be used to get the length of an
- ansistring.
- To set the length of an ansistring, the \seep{SetLength} function must be used.
- Constant ansistrings have a reference count of -1 and are treated specially.
- Ansistrings are converted to short strings by the compiler if needed,
- this means that the use of ansistrings and short strings can be mixed
- without problems.
- Ansistrings can be typecasted to \var{PChar} or \var{Pointer} types:
- \begin{verbatim}
- Var P : Pointer;
- PC : PChar;
- S : AnsiString;
- begin
- S :='This is an ansistring';
- PC:=Pchar(S);
- P :=Pointer(S);
- \end{verbatim}
- There is a difference between the two typecasts. When an empty
- ansistring is typecasted to a pointer, the pointer wil be \var{Nil}. If an
- empty ansistring is typecasted to a \var{PChar}, then the result will be a pointer to a
- zero byte (an empty string).
- The result of such a typecast must be used with care. In general, it is best
- to consider the result of such a typecast as read-only, i.e. suitable for
- passing to a procedure that needs a constant pchar argument.
- It is therefore NOT advisable to typecast one of the following:
- \begin{enumerate}
- \item expressions.
- \item strings that have reference count larger than 0.
- (call uniquestring to ensure a string has reference count 1)
- \end{enumerate}
- \subsection{WideStrings}
- Widestrings (used to represent unicode character strings) are implemented in much
- the same way as ansistrings: reference counted, null-terminated arrays, only they
- are implemented as arrays of \var{WideChars} instead of regular \var{Chars}.
- A \var{WideChar} is a two-byte character (an element of a DBCS: Double Byte
- Character Set). Mostly the same rules apply for \var{WideStrings} as for
- \var{AnsiStrings}. The compiler transparantly converts WideStrings to
- AnsiStrings and vice versa.
- Similarly to the typecast of an Ansistring to a \var{PChar} null-terminated
- array of characters, a WideString can be converted to a \var{PWideChar}
- null-terminated array of characters.
- Note that the \var{PWideChar} array is terminated by 2 null bytes instead of
- 1, so a typecast to a pchar is not automatic.
- The compiler itself provides no support for any conversion from Unicode to
- ansistrings or vice versa; 2 procedural variables are present in the system
- unit which can be set to handle the conversion. For more information, see
- the system units reference.
- % Constant strings
- \subsection{Constant strings}
- To specify a constant string, it must be enclosed in single-quotes, just
- as a \var{Char} type, only now more than one character is allowed.
- Given that \var{S} is of type \var{String}, the following are valid assignments:
- \begin{verbatim}
- S := 'This is a string.';
- S := 'One'+', Two'+', Three';
- S := 'This isn''t difficult !';
- S := 'This is a weird character : '#145' !';
- \end{verbatim}
- As can be seen, the single quote character is represented by 2 single-quote
- characters next to each other. Strange characters can be specified by their
- ASCII value.
- The example shows also that two strings can be added. The resulting string is
- just the concatenation of the first with the second string, without spaces in
- between them. Strings can not be substracted, however.
- Whether the constant string is stored as an ansistring or a short string
- depends on the settings of the \var{\{\$H\}} switch.
- % PChar
- \subsection{PChar - Null terminated strings}
- \fpc supports the Delphi implementation of the \var{PChar} type. \var{PChar}
- is defined as a pointer to a \var{Char} type, but allows additional
- operations.
- The \var{PChar} type can be understood best as the Pascal equivalent of a
- C-style null-terminated string, i.e. a variable of type \var{PChar} is a
- pointer that points to an array of type \var{Char}, which is ended by a
- null-character (\var{\#0}).
- \fpc supports initializing of \var{PChar} typed constants, or a direct
- assignment. For example, the following pieces of code are equivalent:
- \begin{verbatim}
- program one;
- var p : PChar;
- begin
- P := 'This is a null-terminated string.';
- WriteLn (P);
- end.
- \end{verbatim}
- Results in the same as
- \begin{verbatim}
- program two;
- const P : PChar = 'This is a null-terminated string.'
- begin
- WriteLn (P);
- end.
- \end{verbatim}
- These examples also show that it is possible to write {\em the contents} of
- the string to a file of type \var{Text}.
- The \seestrings unit contains procedures and functions that manipulate the
- \var{PChar} type as in the standard C library.
- Since it is equivalent to a pointer to a type \var{Char} variable, it is
- also possible to do the following:
- \begin{verbatim}
- Program three;
- Var S : String[30];
- P : PChar;
- begin
- S := 'This is a null-terminated string.'#0;
- P := @S[1];
- WriteLn (P);
- end.
- \end{verbatim}
- This will have the same result as the previous two examples.
- Null-terminated strings cannot be added as normal Pascal
- strings. If two \var{PChar} strings mustt be concatenated; the functions from
- the unit \seestrings must be used.
- However, it is possible to do some pointer arithmetic. The
- operators \var{+} and \var{-} can be used to do operations on \var{PChar} pointers.
- In \seet{PCharMath}, \var{P} and \var{Q} are of type \var{PChar}, and
- \var{I} is of type \var{Longint}.
- \begin{FPCltable}{lr}{\var{PChar} pointer arithmetic}{PCharMath}
- Operation & Result \\ \hline
- \var{P + I} & Adds \var{I} to the address pointed to by \var{P}. \\
- \var{I + P} & Adds \var{I} to the address pointed to by \var{P}. \\
- \var{P - I} & Substracts \var{I} from the address pointed to by \var{P}. \\
- \var{P - Q} & Returns, as an integer, the distance between 2 addresses \\
- & (or the number of characters between \var{P} and \var{Q}) \\
- \hline
- \end{FPCltable}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Structured Types
- \section{Structured Types}
- A structured type is a type that can hold multiple values in one variable.
- Stuctured types can be nested to unlimited levels.
- \input{syntax/typestru.syn}
- Unlike Delphi, \fpc does not support the keyword \var{Packed} for all
- structured types, as can be seen in the syntax diagram. It will be mentioned
- when a type supports the \var{packed} keyword.
- In the following, each of the possible structured types is discussed.
- \subsection{Arrays}
- \fpc supports arrays as in Turbo Pascal, multi-dimensional arrays
- and packed arrays are also supported, as well as the dynamic arrays of
- Delphi:
- \input{syntax/typearr.syn}
- \subsubsection{Static arrays}
- When the range of the array is included in the array definition, it is
- called a static array. Trying to access an element with an index that is
- outside the declared range will generate a run-time error (if range checking
- is on). The following is an example of a valid array declaration:
- \begin{verbatim}
- Type
- RealArray = Array [1..100] of Real;
- \end{verbatim}
- Valid indexes for accessing an element of the array are between 1 and 100,
- where the borders 1 and 100 are included.
- As in Turbo Pascal, if the array component type is in itself an array, it is
- possible to combine the two arrays into one multi-dimensional array. The
- following declaration:
- \begin{verbatim}
- Type
- APoints = array[1..100] of Array[1..3] of Real;
- \end{verbatim}
- is equivalent to the following declaration:
- \begin{verbatim}
- Type
- APoints = array[1..100,1..3] of Real;
- \end{verbatim}
- The functions \seef{High} and \seef{Low} return the high and low bounds of
- the leftmost index type of the array. In the above case, this would be 100
- and 1.
- When static array-type variables are assigned to each other, the contents of the
- whole array is copied. This is also true for multi-dimensional arrays:
- \begin{verbatim}
- program testarray1;
- Type
- TA = Array[0..9,0..9] of Integer;
-
- var
- A,B : TA;
- I,J : Integer;
- begin
- For I:=0 to 9 do
- For J:=0 to 9 do
- A[I,J]:=I*J;
- For I:=0 to 9 do
- begin
- For J:=0 to 9 do
- Write(A[I,J]:2,' ');
- Writeln;
- end;
- B:=A;
- Writeln;
- For I:=0 to 9 do
- For J:=0 to 9 do
- A[9-I,9-J]:=I*J;
- For I:=0 to 9 do
- begin
- For J:=0 to 9 do
- Write(B[I,J]:2,' ');
- Writeln;
- end;
- end.
- \end{verbatim}
- The output will be 2 identical matrices.
- \subsubsection{Dynamic arrays}
- As of version 1.1, \fpc also knows dynamic arrays: In that case, the array
- range is omitted, as in the following example:
- \begin{verbatim}
- Type
- TByteArray : Array of Byte;
- \end{verbatim}
- When declaring a variable of a dynamic array type, the initial length of the
- array is zero. The actual length of the array must be set with the standard
- \var{SetLength} function, which will allocate the memory to contain the
- array elements on the heap. The following example will set the length to
- 1000:
- \begin{verbatim}
- Var
- A : TByteArray;
- begin
- SetLength(A,1000);
- \end{verbatim}
- After a call to \var{SetLength}, valid array indexes are 0 to 999: the array
- index is always zero-based.
- Note that the length of the array is set in elements, not in bytes of
- allocated memory (although these may be the same). The amount of
- memory allocated is the size of the array multiplied by the size of
- 1 element in the array. The memory will be disposed of at the exit of the
- current procedure or function.
- It is also possible to resize the array: in that case, as much of the
- elements in the array as will fit in the new size, will be kept. The array
- can be resized to zero, which effectively resets the variable.
- At all times, trying to access an element of the array that is not in the
- current length of the array will generate a run-time error.
- Assignment of one dynamic array-type variable to another will let both
- variables point to the same array. Contrary to ansistrings, an
- assignment to an element of one array will be reflected in the
- other:
- \begin{verbatim}
- Var
- A,B : TByteArray;
- begin
- SetLength(A,10);
- A[1]:=33;
- B:=A;
- A[1]:=31;
- \end{verbatim}
- After the second assignment, the first element in B will also contain 31.
- It can also be seen from the output of the following example:
- \begin{verbatim}
- program testarray1;
- Type
- TA = Array of array of Integer;
-
- var
- A,B : TA;
- I,J : Integer;
- begin
- Setlength(A,10,10);
- For I:=0 to 9 do
- For J:=0 to 9 do
- A[I,J]:=I*J;
- For I:=0 to 9 do
- begin
- For J:=0 to 9 do
- Write(A[I,J]:2,' ');
- Writeln;
- end;
- B:=A;
- Writeln;
- For I:=0 to 9 do
- For J:=0 to 9 do
- A[9-I,9-J]:=I*J;
- For I:=0 to 9 do
- begin
- For J:=0 to 9 do
- Write(B[I,J]:2,' ');
- Writeln;
- end;
- end.
- \end{verbatim}
- The output will be a matrix of numbers, and then the same matrix, mirrorred.
- Dynamic arrays are reference counted: if in one of the previous examples A
- goes out of scope and B does not, then the array is not yet disposed of: the
- reference count of A (and B) is decreased with 1. As soon as the reference
- count reaches zero, the memory is disposed of.
- It is also possible to copy and/or resize the array with the standard
- \var{Copy} function, which acts as the copy function for strings:
- \begin{verbatim}
- program testarray3;
- Type
- TA = array of Integer;
-
- var
- A,B : TA;
- I,J : Integer;
- begin
- Setlength(A,10);
- For I:=0 to 9 do
- A[I]:=I;
- B:=Copy(A,3,9);
- For I:=0 to 5 do
- Writeln(B[I]);
- end.
- \end{verbatim}
- The \var{Copy} function will copy 9 elements of the array to a new array.
- Starting at the element at index 3 (i.e. the fourth element) of the array.
- The \var{Low} function on a dynamic array will always return 0, and the
- High function will return the value \var{Length-1}, i.e., the value of the
- highest allowed array index. The \var{Length} function will return the
- number of elements in the array.
- \subsection{Record types}
- \fpc supports fixed records and records with variant parts.
- The syntax diagram for a record type is
- \input{syntax/typerec.syn}
- So the following are valid record types declarations:
- \begin{verbatim}
- Type
- Point = Record
- X,Y,Z : Real;
- end;
- RPoint = Record
- Case Boolean of
- False : (X,Y,Z : Real);
- True : (R,theta,phi : Real);
- end;
- BetterRPoint = Record
- Case UsePolar : Boolean of
- False : (X,Y,Z : Real);
- True : (R,theta,phi : Real);
- end;
- \end{verbatim}
- The variant part must be last in the record. The optional identifier in the
- case statement serves to access the tag field value, which otherwise would
- be invisible to the programmer. It can be used to see which variant is
- active at a certain time. In effect, it introduces a new field in the
- record.
- \begin{remark}
- It is possible to nest variant parts, as in:
- \begin{verbatim}
- Type
- MyRec = Record
- X : Longint;
- Case byte of
- 2 : (Y : Longint;
- case byte of
- 3 : (Z : Longint);
- );
- end;
- \end{verbatim}
- \end{remark}
- The size of a record is the sum of the sizes of its fields, each size of a
- field is rounded up to a power of two. If the record contains a variant part, the size
- of the variant part is the size of the biggest variant, plus the size of the
- tag field type {\em if an identifier was declared for it}. Here also, the size of
- each part is first rounded up to two. So in the above example,
- \seef{SizeOf} would return 24 for \var{Point}, 24 for \var{RPoint} and
- 26 for \var{BetterRPoint}. For \var{MyRec}, the value would be 12.
- If a typed file with records, produced by a Turbo Pascal program, must be read,
- then chances are that attempting to read that file correctly will fail.
- The reason for this is that by default, elements of a record are aligned at
- 2-byte boundaries, for performance reasons. This default behaviour can be
- changed with the \var{\{\$PackRecords n\}} switch. Possible values for
- \var{n} are 1, 2, 4, 16 or \var{Default}.
- This switch tells the compiler to align elements of a record or object or
- class that have size larger than \var{n} on \var{n} byte boundaries.
- Elements that have size smaller or equal than \var{n} are aligned on
- natural boundaries, i.e. to the first power of two that is larger than or
- equal to the size of the record element.
- The keyword \var{Default} selects the default value for the platform
- that the code is compiled for (currently, this is 2 on all platforms)
- Take a look at the following program:
- \begin{verbatim}
- Program PackRecordsDemo;
- type
- {$PackRecords 2}
- Trec1 = Record
- A : byte;
- B : Word;
- end;
- {$PackRecords 1}
- Trec2 = Record
- A : Byte;
- B : Word;
- end;
- {$PackRecords 2}
- Trec3 = Record
- A,B : byte;
- end;
- {$PackRecords 1}
- Trec4 = Record
- A,B : Byte;
- end;
- {$PackRecords 4}
- Trec5 = Record
- A : Byte;
- B : Array[1..3] of byte;
- C : byte;
- end;
- {$PackRecords 8}
- Trec6 = Record
- A : Byte;
- B : Array[1..3] of byte;
- C : byte;
- end;
- {$PackRecords 4}
- Trec7 = Record
- A : Byte;
- B : Array[1..7] of byte;
- C : byte;
- end;
- {$PackRecords 8}
- Trec8 = Record
- A : Byte;
- B : Array[1..7] of byte;
- C : byte;
- end;
- Var rec1 : Trec1;
- rec2 : Trec2;
- rec3 : TRec3;
- rec4 : TRec4;
- rec5 : Trec5;
- rec6 : TRec6;
- rec7 : TRec7;
- rec8 : TRec8;
- begin
- Write ('Size Trec1 : ',SizeOf(Trec1));
- Writeln (' Offset B : ',Longint(@rec1.B)-Longint(@rec1));
- Write ('Size Trec2 : ',SizeOf(Trec2));
- Writeln (' Offset B : ',Longint(@rec2.B)-Longint(@rec2));
- Write ('Size Trec3 : ',SizeOf(Trec3));
- Writeln (' Offset B : ',Longint(@rec3.B)-Longint(@rec3));
- Write ('Size Trec4 : ',SizeOf(Trec4));
- Writeln (' Offset B : ',Longint(@rec4.B)-Longint(@rec4));
- Write ('Size Trec5 : ',SizeOf(Trec5));
- Writeln (' Offset B : ',Longint(@rec5.B)-Longint(@rec5),
- ' Offset C : ',Longint(@rec5.C)-Longint(@rec5));
- Write ('Size Trec6 : ',SizeOf(Trec6));
- Writeln (' Offset B : ',Longint(@rec6.B)-Longint(@rec6),
- ' Offset C : ',Longint(@rec6.C)-Longint(@rec6));
- Write ('Size Trec7 : ',SizeOf(Trec7));
- Writeln (' Offset B : ',Longint(@rec7.B)-Longint(@rec7),
- ' Offset C : ',Longint(@rec7.C)-Longint(@rec7));
- Write ('Size Trec8 : ',SizeOf(Trec8));
- Writeln (' Offset B : ',Longint(@rec8.B)-Longint(@rec8),
- ' Offset C : ',Longint(@rec8.C)-Longint(@rec8));
- end.
- \end{verbatim}
- The output of this program will be :
- \begin{verbatim}
- Size Trec1 : 4 Offset B : 2
- Size Trec2 : 3 Offset B : 1
- Size Trec3 : 2 Offset B : 1
- Size Trec4 : 2 Offset B : 1
- Size Trec5 : 8 Offset B : 4 Offset C : 7
- Size Trec6 : 8 Offset B : 4 Offset C : 7
- Size Trec7 : 12 Offset B : 4 Offset C : 11
- Size Trec8 : 16 Offset B : 8 Offset C : 15
- \end{verbatim}
- And this is as expected. In \var{Trec1}, since \var{B} has size 2, it is
- aligned on a 2 byte boundary, thus leaving an empty byte between \var{A}
- and \var{B}, and making the total size 4. In \var{Trec2}, \var{B} is aligned
- on a 1-byte boundary, right after \var{A}, hence, the total size of the
- record is 3.
- For \var{Trec3}, the sizes of \var{A,B} are 1, and hence they are aligned on 1
- byte boundaries. The same is true for \var{Trec4}.
- For \var{Trec5}, since the size of B -- 3 -- is smaller than 4, \var{B} will
- be on a 4-byte boundary, as this is the first power of two that is
- larger than it's size. The same holds for \var{Trec6}.
- For \var{Trec7}, \var{B} is aligned on a 4 byte boundary, since it's size --
- 7 -- is larger than 4. However, in \var{Trec8}, it is aligned on a 8-byte
- boundary, since 8 is the first power of two that is greater than 7, thus
- making the total size of the record 16.
- \fpc supports also the 'packed record', this is a record where all the
- elements are byte-aligned.
- Thus the two following declarations are equivalent:
- \begin{verbatim}
- {$PackRecords 1}
- Trec2 = Record
- A : Byte;
- B : Word;
- end;
- {$PackRecords 2}
- \end{verbatim}
- and
- \begin{verbatim}
- Trec2 = Packed Record
- A : Byte;
- B : Word;
- end;
- \end{verbatim}
- Note the \var{\{\$PackRecords 2\}} after the first declaration !
- \subsection{Set types}
- \fpc supports the set types as in Turbo Pascal. The prototype of a set
- declaration is:
- \input{syntax/typeset.syn}
- Each of the elements of \var{SetType} must be of type \var{TargetType}.
- \var{TargetType} can be any ordinal type with a range between \var{0} and
- \var{255}. A set can contain maximally \var{255} elements.
- The following are valid set declaration:
- \begin{verbatim}
- Type
- Junk = Set of Char;
- Days = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
- WorkDays : Set of days;
- \end{verbatim}
- Given this set declarations, the following assignment is legal:
- \begin{verbatim}
- WorkDays := [ Mon, Tue, Wed, Thu, Fri];
- \end{verbatim}
- The operators and functions for manipulations of sets are listed in
- \seet{SetOps}.
- \begin{FPCltable}{lr}{Set Manipulation operators}{SetOps}
- Operation & Operator \\ \hline
- Union & + \\
- Difference & - \\
- Intersection & * \\
- Add element & \var{include} \\
- Delete element & \var{exclude} \\ \hline
- \end{FPCltable}
- Two sets can be compared with the \var{<>} and \var{=} operators, but not
- (yet) with the \var{<} and \var{>} operators.
- The compiler stores small sets (less than 32 elements) in a Longint, if the
- type range allows it. This allows for faster processing and decreases
- program size. Otherwise, sets are stored in 32 bytes.
- \subsection{File types}
- File types are types that store a sequence of some base type, which can be
- any type except another file type. It can contain (in principle) an infinite
- number of elements.
- File types are used commonly to store data on disk. Nothing prevents the programmer,
- however, from writing a file driver that stores it's data in memory.
- Here is the type declaration for a file type:
- \input{syntax/typefil.syn}
- If no type identifier is given, then the file is an untyped file; it can be
- considered as equivalent to a file of bytes. Untyped files require special
- commands to act on them (see \seep{Blockread}, \seep{Blockwrite}).
- The following declaration declares a file of records:
- \begin{verbatim}
- Type
- Point = Record
- X,Y,Z : real;
- end;
- PointFile = File of Point;
- \end{verbatim}
- Internally, files are represented by the \var{FileRec} record, which is
- declared in the DOS unit.
- A special file type is the \var{Text} file type, represented by the
- \var{TextRec} record. A file of type \var{Text} uses special input-output
- routines.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Pointers
- \section{Pointers}
- \fpc supports the use of pointers. A variable of the pointer type
- contains an address in memory, where the data of another variable may be
- stored.
- \input{syntax/typepoin.syn}
- As can be seen from this diagram, pointers are typed, which means that
- they point to a particular kind of data. The type of this data must be
- known at compile time.
- Dereferencing the pointer (denoted by adding \var{\^{}} after the variable
- name) behaves then like a variable. This variable has the type declared in
- the pointer declaration, and the variable is stored in the address that is
- pointed to by the pointer variable.
- Consider the following example:
- \begin{verbatim}
- Program pointers;
- type
- Buffer = String[255];
- BufPtr = ^Buffer;
- Var B : Buffer;
- BP : BufPtr;
- PP : Pointer;
- etc..
- \end{verbatim}
- In this example, \var{BP} {\em is a pointer to} a \var{Buffer} type; while \var{B}
- {\em is} a variable of type \var{Buffer}. \var{B} takes 256 bytes memory,
- and \var{BP} only takes 4 bytes of memory (enough to keep an adress in
- memory).
- \begin{remark} \fpc treats pointers much the same way as C does. This means
- that a pointer to some type can be treated as being an array of this type.
- The pointer then points to the zeroeth element of this array. Thus the
- following pointer declaration
- \begin{verbatim}
- Var p : ^Longint;
- \end{verbatim}
- Can be considered equivalent to the following array declaration:
- \begin{verbatim}
- Var p : array[0..Infinity] of Longint;
- \end{verbatim}
- The difference is that the former declaration allocates memory for the
- pointer only (not for the array), and the second declaration allocates
- memory for the entire array. If the former is used, the memory must be
- allocated manually, using the \seep{Getmem} function.
- The reference \var{P\^{}} is then the same as \var{p[0]}. The following program
- illustrates this maybe more clear:
- \begin{verbatim}
- program PointerArray;
- var i : Longint;
- p : ^Longint;
- pp : array[0..100] of Longint;
- begin
- for i := 0 to 100 do pp[i] := i; { Fill array }
- p := @pp[0]; { Let p point to pp }
- for i := 0 to 100 do
- if p[i]<>pp[i] then
- WriteLn ('Ohoh, problem !')
- end.
- \end{verbatim}
- \end{remark}
- \fpc supports pointer arithmetic as C does. This means that, if \var{P} is a
- typed pointer, the instructions
- \begin{verbatim}
- Inc(P);
- Dec(P);
- \end{verbatim}
- Will increase, respectively decrease the address the pointer points to
- with the size of the type \var{P} is a pointer to. For example
- \begin{verbatim}
- Var P : ^Longint;
- ...
- Inc (p);
- \end{verbatim}
- will increase \var{P} with 4.
- Normal arithmetic operators on pointers can also be used, that is, the
- following are valid pointer arithmetic operations:
- \begin{verbatim}
- var p1,p2 : ^Longint;
- L : Longint;
- begin
- P1 := @P2;
- P2 := @L;
- L := P1-P2;
- P1 := P1-4;
- P2 := P2+4;
- end.
- \end{verbatim}
- Here, the value that is added or substracted {\em is } multiplied by the
- size of the type the pointer points to. In the previous
- example \var{P1} will be decremented by 16 bytes, and
- \var{P2} will be incremented by 16.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Forward type declarations
- \section{Forward type declarations}
- Programs often need to maintain a linked list of records. Each record then
- contains a pointer to the next record (and possibly to the previous record
- as well). For type safety, it is best to define this pointer as a typed
- pointer, so the next record can be allocated on the heap using the \var{New}
- call. In order to do so, the record should be defined something like this:
- \begin{verbatim}
- Type
- TListItem = Record
- Data : Integer;
- Next : ^TListItem;
- end;
- \end{verbatim}
- When trying to compile this, the compiler will complain that the
- \var{TListItem} type is not yet defined when it encounters the \var{Next}
- declaration: This is correct, as the definition is still being parsed.
- To be able to have the \var{Next} element as a typed pointer, a 'Forward
- type declaration' must be introduced:
- \begin{verbatim}
- Type
- PListItem = ^TListItem;
- TListItem = Record
- Data : Integer;
- Next : PTListItem;
- end;
- \end{verbatim}
- When the compiler encounters a typed pointer declaration where the
- referenced type is not yet known, it postpones resolving the reference later
- on: The pointer definition is a 'Forward type declaration'. The referenced
- type should be introduced later in the same \var{Type} block. No other block
- may come between the definition of the pointer type and the referenced type.
- Indeed, even the word \var{Type} itself may not re-appear: in effect it
- would start a new type-block, causing the compiler to resolve all pending
- declarations in the current block. In most cases, the definition of the
- referenced type will follow immediatly after the definition of the pointer
- type, as shown in the above listing. The forward defined type can be used in
- any type definition following its declaration.
- Note that a forward type declaration is only possible with pointer types and
- classes, not with other types.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Procedural types
- \section{Procedural types}
- \fpc has support for procedural types, although it differs a little from
- the Turbo Pascal implementation of them. The type declaration remains the
- same, as can be seen in the following syntax diagram:
- \input{syntax/typeproc.syn}
- For a description of formal parameter lists, see \seec{Procedures}.
- The two following examples are valid type declarations:
- \begin{verbatim}
- Type TOneArg = Procedure (Var X : integer);
- TNoArg = Function : Real;
- var proc : TOneArg;
- func : TNoArg;
- \end{verbatim}
- One can assign the following values to a procedural type variable:
- \begin{enumerate}
- \item \var{Nil}, for both normal procedure pointers and method pointers.
- \item A variable reference of a procedural type, i.e. another variable of
- the same type.
- \item A global procedure or function address, with matching function or
- procedure header and calling convention.
- \item A method address.
- \end{enumerate}
- Given these declarations, the following assignments are valid:
- \begin{verbatim}
- Procedure printit (Var X : Integer);
- begin
- WriteLn (x);
- end;
- ...
- Proc := @printit;
- Func := @Pi;
- \end{verbatim}
- From this example, the difference with Turbo Pascal is clear: In Turbo
- Pascal it isn't necessary to use the address operator (\var{@})
- when assigning a procedural type variable, whereas in \fpc it is required
- (unless the \var{-So} switch is used, in which case the address
- operator can be dropped.)
- \begin{remark} The modifiers concerning the calling conventions
- must be the same as the declaration;
- i.e. the following code would give an error:
- \begin{verbatim}
- Type TOneArgCcall = Procedure (Var X : integer);cdecl;
- var proc : TOneArgCcall;
- Procedure printit (Var X : Integer);
- begin
- WriteLn (x);
- end;
- begin
- Proc := @printit;
- end.
- \end{verbatim}
- Because the \var{TOneArgCcall} type is a procedure that uses the cdecl
- calling convention.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Variant types
- \section{Variant types}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Definition
- \subsection{Definition}
- As of version 1.1, FPC has support for variants. For variant support to be
- enabled, the \file{variants} unit must be included in every unit that uses
- variants in some way. Furthermore, the compiler must be in \var{Delphi} or
- \var{ObjFPC} mode.
- The type of a value stored in a variant is only determined at runtime:
- it depends what has been assigned to the to the variant. Almost any type
- can be assigned to variants: ordinal types, string types, int64 types.
- Structured types such as sets, records, arrays, files, objects and classes
- are not assign-compatible with a variant, as well as pointers. Interfaces
- and COM or CORBA objects can be assigned to a variant.
- This means that the following assignments are valid:
- \begin{verbatim}
- Type
- TMyEnum = (One,Two,Three);
- Var
- V : Variant;
- I : Integer;
- B : Byte;
- W : Word;
- Q : Int64;
- E : Extended;
- D : Double;
- En : TMyEnum;
- AS : AnsiString;
- WS : WideString;
- begin
- V:=I;
- V:=B;
- V:=W;
- V:=Q;
- V:=E;
- V:=En;
- V:=D:
- V:=AS;
- V:=WS;
- end;
- \end{verbatim}
- And of course vice-versa as well.
- \begin{remark}
- The enumerated type assignment is broken in the early 1.1 development series of the
- compiler. It is expected that this is fixed soon.
- \end{remark}
- A variant can hold an an array of values: All elements in the array have the
- same type (but can be of type 'variant'). For a variant that contains an
- array, the variant can be indexed:
- \begin{verbatim}
- Program testv;
- uses variants;
- Var
- A : Variant;
- I : integer;
- begin
- A:=VarArrayCreate([1,10],varInteger);
- For I:=1 to 10 do
- A[I]:=I;
- end.
- \end{verbatim}
- (for the explanation of \var{VarArrayCreate}, see \unitsref.)
- Note that when the array contains a string, this is not considered an 'array
- of characters', and so the variant cannot be indexed to retrieve a character
- at a certain position in the string.
- \begin{remark}
- The array functionality is broken in the early 1.1 development series of the
- compiler. It is expected that this is fixed soon.
- \end{remark}
- \subsection{Variants in assignments and expressions}
- As can be seen from the definition above, most simple types can be assigned
- to a variant. Likewise, a variant can be assigned to a simple type: If
- possible, the value of the variant will be converted to the type that is
- being assigned to. This may fail: Assigning a variant containing a string
- to an integer will fail unless the string represents a valid integer. In the
- following example, the first assignment will work, the second will fail:
- \begin{verbatim}
- program testv3;
- uses Variants;
- Var
- V : Variant;
- I : Integer;
- begin
- V:='100';
- I:=V;
- Writeln('I : ',I);
- V:='Something else';
- I:=V;
- Writeln('I : ',I);
- end.
- \end{verbatim}
- The first assignment will work, but the second will not, as \var{Something else}
- cannot be converted to a valid integer value. An \var{EConvertError} exception
- will be the result.
- The result of an expression involving a variant will be of type variant again,
- but this can be assigned to a variable of a different type - if the result
- can be converted to a variable of this type.
- Note that expressions involving variants take more time to be evaluated, and
- should therefore be used with caution. If a lot of calculations need to be
- made, it is best to avoid the use of variants.
- When considering implicit type conversions (e.g. byte to integer, integer to
- double, char to string) the compiler will ignore variants unless a variant
- appears explicitly in the expression.
-
- \subsection{Variants and interfaces}
- \begin{remark}
- Dispatch interface support for variants is currently broken in the compiler.
- \end{remark}
- Variants can contain a reference to an interface - a normal interface
- (descending from \var{IInterface}) or a dispatchinterface (descending
- from \var{IDispatch}). Variants containing a reference to a dispatch
- interface can be used to control the object behind it: the compiler will use
- late binding to perform the call to the dispatch interface: there will be no
- run-time checking of the function names and parameters or arguments given to
- the functions. The result type is also not checked. The compiler will simply
- insert code to make the dispatch call and retrieve the result.
- This means basically, that you can do the following on Windows:
- \begin{verbatim}
- Var
- W : Variant;
- V : String;
- begin
- W:=CreateOleObject('Word.Application');
- V:=W.Application.Version;
- Writeln('Installed version of MS Word is : ',V);
- end;
- \end{verbatim}
- The line
- \begin{verbatim}
- V:=W.Application.Version;
- \end{verbatim}
- is executed by inserting the necessary code to query the dispatch interface
- stored in the variant \var{W}, and execute the call if the needed dispatch
- information is found.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Variables
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Variables}
- \label{ch:Variables}
- \section{Definition}
- Variables are explicitly named memory locations with a certain type. When
- assigning values to variables, the \fpc compiler generates machine code
- to move the value to the memory location reserved for this variable. Where
- this variable is stored depends on where it is declared:
- \begin{itemize}
- \item Global variables are variables declared in a unit or program, but not
- inside a procedure or function. They are stored in fixed memory locations,
- and are available during the whole execution time of the program.
- \item Local variables are declared inside a procedure or function. Their
- value is stored on the program stack, i.e. not at fixed locations.
- \end{itemize}
- The \fpc compiler handles the allocation of these memory locations
- transparantly, although this location can be influenced in the declaration.
- The \fpc compiler also handles reading values from or writing values to
- the variables transparantly. But even this can be explicitly handled by the
- programmer when using properties.
- Variables must be explicitly declared when they are needed. No memory is
- allocated unless a variable is declared. Using an variable identifier (for
- instance, a loop variable) which is not declared first, is an error which
- will be reported by the compiler.
- \section{Declaration}
- The variables must be declared in a variable declaration section of a unit
- or a procedure or function. It looks as follows:
- \input{syntax/vardecl.syn}
- This means that the following are valid variable declarations:
- \begin{verbatim}
- Var
- curterm1 : integer;
- curterm2 : integer; cvar;
- curterm3 : integer; cvar; external;
- curterm4 : integer; external name 'curterm3';
- curterm5 : integer; external 'libc' name 'curterm9';
- curterm6 : integer absolute curterm1;
- curterm7 : integer; cvar; export;
- curterm8 : integer; cvar; public;
- curterm9 : integer; export name 'me';
- curterm10 : integer; public name 'ma';
- curterm11 : integer = 1 ;
- \end{verbatim}
- The difference between these declarations is as follows:
- \begin{enumerate}
- \item The first form (\var{curterm1}) defines a regular variable. The
- compiler manages everything by itself.
- \item The second form (\var{curterm2}) declares also a regular variable,
- but specifies that the assembler name for this variable equals the name
- of the variable as written in the source.
- \item The third form (\var{curterm3}) declares a variable which is located
- externally: the compiler will assume memory is located elsewhere, and that
- the assembler name of this location is specified by the name of the
- variable, as written in the source. The name may not be specified.
- \item The fourth form is completely equivalent to the third, it declares a
- variable which is stored externally, and explicitly gives the assembler
- name of the location. If \var{cvar} is not used, the name must be specified.
- \item The fifth form is a variant of the fourth form, only the name of the
- library in which the memory is reserved is specified as well.
- \item The sixth form declares a variable (\var{curterm6}), and tells the compiler that it is
- stored in the same location as another variable (\var{curterm1})
- \item The seventh form declares a variable (\var{curterm7}), and tells the
- compiler that the assembler label of this variable should be the name of the
- variable (case sensitive) and must be made public. (i.e. it can be
- referenced from other object files)
- \item The eight form (\var{curterm8}) is equivalent to the seventh: 'public'
- is an alias for 'export'.
- \item The ninth and tenth form are equivalent: they specify the assembler
- name of the variable.
- \item the elevents form declares a variable (\var{curterm11}) and
- initializes it with a value (1 in the above case).
- \end{enumerate}
- Note that assembler names must be unique. It's not possible to declare or
- export 2 variables with the same assembler name.
- \section{Scope}
- Variables, just as any identifier, obey the general rules of scope.
- In addition, initialized variables are initialized when they enter scope:
- \begin{itemize}
- \item Global initialized variables are initialized once, when the program starts.
- \item Local initialized variables are initialized each time the procedure is
- entered.
- \end{itemize}
- Note that the behaviour for local initialized variables is different from
- the one of a local typed constant. A local typed constant behaves like a
- global initialized variable.
- \section{Thread Variables}
- For a program which uses threads, the variables can be really global, i.e. the same for all
- threads, or thread-local: this means that each thread gets a copy of the variable.
- Local variables (defined inside a procedure) are always thread-local. Global
- variables are normally the same for all threads. A global variable can be
- declared thread-local by replacing the \var{var} keyword at the start of the
- variable declaration block with \var{Threadvar}:
- \begin{verbatim}
- Threadvar
- IOResult : Integer;
- \end{verbatim}
- If no threads are used, the variable behaves as an ordinary variable.
- If threads are used then a copy is made
- for each thread (including the main thread). Note that the copy is
- made with the original value of the variable, {\em not} with the
- value of the variable at the time the thread is started.
- Threadvars should be used sparingly: There is an overhead for retrieving
- or setting the variable's value. If possible at all, consider using local
- variables; they are always faster than thread variables.
- Threads are not enabled by default. For more information about programming
- threads, see the chapter on threads in the \progref.
- \section{Properties}
- A global block can declare properties, just as they could be defined in a
- class. The difference is that the global property does not need a class
- instance: there is only 1 instance of this property. Other than that, a
- global property behaves like a class property. The read/write specifiers for
- the global property must also be regular procedures, not methods.
- The concept of a global property is specific to \fpc, and does not exist in
- Delphi.
- The concept of a global property can be used to 'hide' the location of the
- value, or to calculate the value on the fly, or to check the values which
- are written to the property.
- The declaration is as follows:
- \input{syntax/propvar.syn}
- The following is an example:
- \begin{verbatim}
- {$mode objfpc}
- unit testprop;
- Interface
- Function GetMyInt : Integer;
- Procedure SetMyInt(Value : Integer);
- Property
- MyProp : Integer Read GetMyInt Write SetMyInt;
-
- Implementation
- Uses sysutils;
- Var
- FMyInt : Integer;
-
- Function GetMyInt : Integer;
- begin
- Result:=FMyInt;
- end;
- Procedure SetMyInt(Value : Integer);
- begin
- If ((Value mod 2)=1) then
- Raise Exception.Create('MyProp can only contain even value');
- FMyInt:=Value;
- end;
- end.
- \end{verbatim}
- The read/write specifiers can be hidden by declaring them in another unit
- which must be in the \var{uses} clause of the unit. This can be used to hide
- the read/write access specifiers for programmers, just as if they were in a
- \var{private} section of a class (discussed below). For the previous
- example, this could look as follows:
- \begin{verbatim}
- {$mode objfpc}
- unit testrw;
- Interface
- Function GetMyInt : Integer;
- Procedure SetMyInt(Value : Integer);
- Implementation
- Uses sysutils;
- Var
- FMyInt : Integer;
-
- Function GetMyInt : Integer;
- begin
- Result:=FMyInt;
- end;
- Procedure SetMyInt(Value : Integer);
- begin
- If ((Value mod 2)=1) then
- Raise Exception.Create('Only even values are allowed');
- FMyInt:=Value;
- end;
- end.
- \end{verbatim}
- The unit \file{testprop} would then look like:
- \begin{verbatim}
- {$mode objfpc}
- unit testprop;
- Interface
- uses testrw;
- Property
- MyProp : Integer Read GetMyInt Write SetMyInt;
- Implementation
- end.
- \end{verbatim}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Objects
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Objects}
- \label{ch:Objects}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Declaration
- \section{Declaration}
- \fpc supports object oriented programming. In fact, most of the compiler is
- written using objects. Here we present some technical questions regarding
- object oriented programming in \fpc.
- Objects should be treated as a special kind of record. The record contains
- all the fields that are declared in the objects definition, and pointers
- to the methods that are associated to the objects' type.
- An object is declared just as a record would be declared; except that
- now,procedures and functions can be declared as if they were part of the record.
- Objects can ''inherit'' fields and methods from ''parent'' objects. This means
- that these fields and methods can be used as if they were included in the
- objects declared as a ''child'' object.
- Furthermore, a concept of visibility is introduced: fields, procedures and functions
- can be delcared as \var{public} or \var{private}. By default, fields and
- methods are \var{public}, and are
- exported outside the current unit. Fields or methods that are declared
- \var{private} are only accessible in the current unit.
- The prototype declaration of an object is as follows:
- \input{syntax/typeobj.syn}
- As can be seen, as many \var{private} and \var{public} blocks as needed can be
- declared.
- \var{Method definitions} are normal function or procedure declarations.
- Fields cannot be declared after methods in the same block, i.e. the following
- will generate an error when compiling:
- \begin{verbatim}
- Type MyObj = Object
- Procedure Doit;
- Field : Longint;
- end;
- \end{verbatim}
- But the following will be accepted:
- \begin{verbatim}
- Type MyObj = Object
- Public
- Procedure Doit;
- Private
- Field : Longint;
- end;
- \end{verbatim}
- because the field is in a different section.
- \begin{remark}
- \fpc also supports the packed object. This is the same as an object, only
- the elements (fields) of the object are byte-aligned, just as in the packed
- record.
- The declaration of a packed object is similar to the declaration
- of a packed record :
- \begin{verbatim}
- Type
- TObj = packed object;
- Constructor init;
- ...
- end;
- Pobj = ^TObj;
- Var PP : Pobj;
- \end{verbatim}
- Similarly, the \var{\{\$PackRecords \}} directive acts on objects as well.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Fields
- \section{Fields}
- Object Fields are like record fields. They are accessed in the same way as
- a record field would be accessed : by using a qualified identifier. Given the
- following declaration:
- \begin{verbatim}
- Type TAnObject = Object
- AField : Longint;
- Procedure AMethod;
- end;
- Var AnObject : TAnObject;
- \end{verbatim}
- then the following would be a valid assignment:
- \begin{verbatim}
- AnObject.AField := 0;
- \end{verbatim}
- Inside methods, fields can be accessed using the short identifier:
- \begin{verbatim}
- Procedure TAnObject.AMethod;
- begin
- ...
- AField := 0;
- ...
- end;
- \end{verbatim}
- Or, one can use the \var{self} identifier. The \var{self} identifier refers
- to the current instance of the object:
- \begin{verbatim}
- Procedure TAnObject.AMethod;
- begin
- ...
- Self.AField := 0;
- ...
- end;
- \end{verbatim}
- One cannot access fields that are in a private section of an object from
- outside the objects' methods. If this is attempted anyway, the compiler will complain about
- an unknown identifier.
- It is also possible to use the \var{with} statement with an object instance:
- \begin{verbatim}
- With AnObject do
- begin
- Afield := 12;
- AMethod;
- end;
- \end{verbatim}
- In this example, between the \var{begin} and \var{end}, it is as if
- \var{AnObject} was prepended to the \var{Afield} and \var{Amethod}
- identifiers. More about this in \sees{With}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Constructors and destructors
- \section{Constructors and destructors }
- \label{se:constructdestruct}
- As can be seen in the syntax diagram for an object declaration, \fpc supports
- constructors and destructors. The programmer is responsible for calling the
- constructor and the destructor explicitly when using objects.
- The declaration of a constructor or destructor is as follows:
- \input{syntax/construct.syn}
- A constructor/destructor pair is {\em required} if the object uses virtual methods.
- In the declaration of the object type, a simple identifier should be used
- for the name of the constuctor or destructor. When the constructor or destructor
- is implemented, A qualified method identifier should be used,
- i.e. an identifier of the form \var{objectidentifier.methodidentifier}.
- \fpc supports also the extended syntax of the \var{New} and \var{Dispose}
- procedures. In case a dynamic variable of an object type must be allocated
- the constructor's name can be specified in the call to \var{New}.
- The \var{New} is implemented as a function which returns a pointer to the
- instantiated object. Consider the following declarations:
- \begin{verbatim}
- Type
- TObj = object;
- Constructor init;
- ...
- end;
- Pobj = ^TObj;
- Var PP : Pobj;
- \end{verbatim}
- Then the following 3 calls are equivalent:
- \begin{verbatim}
- pp := new (Pobj,Init);
- \end{verbatim}
- and
- \begin{verbatim}
- new(pp,init);
- \end{verbatim}
- and also
- \begin{verbatim}
- new (pp);
- pp^.init;
- \end{verbatim}
- In the last case, the compiler will issue a warning that the
- extended syntax of \var{new} and \var{dispose} must be used to generate instances of an
- object. It is possible to ignore this warning, but it's better programming practice to
- use the extended syntax to create instances of an object.
- Similarly, the \var{Dispose} procedure accepts the name of a destructor. The
- destructor will then be called, before removing the object from the heap.
- In view of the compiler warning remark, the following chapter presents the
- Delphi approach to object-oriented programming, and may be considered a
- more natural way of object-oriented programming.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Methods
- \section{Methods}
- Object methods are just like ordinary procedures or functions, only they
- have an implicit extra parameter : \var{self}. Self points to the object
- with which the method was invoked.
- When implementing methods, the fully qualified identifier must be given
- in the function header. When declaring methods, a normal identifier must be
- given.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Method invocation
- \section{Method invocation}
- Methods are called just as normal procedures are called, only they have an
- object instance identifier prepended to them (see also \seec{Statements}).
- To determine which method is called, it is necessary to know the type of
- the method. We treat the different types in what follows.
- \subsubsection{Static methods}
- Static methods are methods that have been declared without a \var{abstract}
- or \var{virtual} keyword. When calling a static method, the declared (i.e.
- compile time) method of the object is used.
- For example, consider the following declarations:
- \begin{verbatim}
- Type
- TParent = Object
- ...
- procedure Doit;
- ...
- end;
- PParent = ^TParent;
- TChild = Object(TParent)
- ...
- procedure Doit;
- ...
- end;
- PChild = ^TChild;
- \end{verbatim}
- As it is visible, both the parent and child objects have a method called
- \var{Doit}. Consider now the following declarations and calls:
- \begin{verbatim}
- Var ParentA,ParentB : PParent;
- Child : PChild;
- ParentA := New(PParent,Init);
- ParentB := New(PChild,Init);
- Child := New(PChild,Init);
- ParentA^.Doit;
- ParentB^.Doit;
- Child^.Doit;
- \end{verbatim}
- Of the three invocations of \var{Doit}, only the last one will call
- \var{TChild.Doit}, the other two calls will call \var{TParent.Doit}.
- This is because for static methods, the compiler determines at compile
- time which method should be called. Since \var{ParentB} is of type
- \var{TParent}, the compiler decides that it must be called with
- \var{TParent.Doit}, even though it will be created as a \var{TChild}.
- There may be times when the method that is actually called should
- depend on the actual type of the object at run-time. If so, the method
- cannot be a static method, but must be a virtual method.
- \subsubsection{Virtual methods}
- To remedy the situation in the previous section, \var{virtual} methods are
- created. This is simply done by appending the method declaration with the
- \var{virtual} modifier.
- Going back to the previous example, consider the following alternative
- declaration:
- \begin{verbatim}
- Type
- TParent = Object
- ...
- procedure Doit;virtual;
- ...
- end;
- PParent = ^TParent;
- TChild = Object(TParent)
- ...
- procedure Doit;virtual;
- ...
- end;
- PChild = ^TChild;
- \end{verbatim}
- As it is visible, both the parent and child objects have a method called
- \var{Doit}. Consider now the following declarations and calls :
- \begin{verbatim}
- Var ParentA,ParentB : PParent;
- Child : PChild;
- ParentA := New(PParent,Init);
- ParentB := New(PChild,Init);
- Child := New(PChild,Init);
- ParentA^.Doit;
- ParentB^.Doit;
- Child^.Doit;
- \end{verbatim}
- Now, different methods will be called, depending on the actual run-time type
- of the object. For \var{ParentA}, nothing changes, since it is created as
- a \var{TParent} instance. For \var{Child}, the situation also doesn't
- change: it is again created as an instance of \var{TChild}.
- For \var{ParentB} however, the situation does change: Even though it was
- declared as a \var{TParent}, it is created as an instance of \var{TChild}.
- Now, when the program runs, before calling \var{Doit}, the program
- checks what the actual type of \var{ParentB} is, and only then decides which
- method must be called. Seeing that \var{ParentB} is of type \var{TChild},
- \var{TChild.Doit} will be called.
- The code for this run-time checking of the actual type of an object is
- inserted by the compiler at compile time.
- The \var{TChild.Doit} is said to {\em override} the \var{TParent.Doit}.
- It is possible to acces the \var{TParent.Doit} from within the
- var{TChild.Doit}, with the \var{inherited} keyword:
- \begin{verbatim}
- Procedure TChild.Doit;
- begin
- inherited Doit;
- ...
- end;
- \end{verbatim}
- In the above example, when \var{TChild.Doit} is called, the first thing it
- does is call \var{TParent.Doit}. The inherited keyword cannot be used in
- static methods, only on virtual methods.
- \subsubsection{Abstract methods}
- An abstract method is a special kind of virtual method. A method can not be
- abstract if it is not virtual (this is not obvious from the syntax diagram).
- An instance of an object that has an abstract method cannot be created directly.
- The reason is obvious: there is no method where the compiler could jump to !
- A method that is declared \var{abstract} does not have an implementation for
- this method. It is up to inherited objects to override and implement this
- method. Continuing our example, take a look at this:
- \begin{verbatim}
- Type
- TParent = Object
- ...
- procedure Doit;virtual;abstract;
- ...
- end;
- PParent=^TParent;
- TChild = Object(TParent)
- ...
- procedure Doit;virtual;
- ...
- end;
- PChild = ^TChild;
- \end{verbatim}
- As it is visible, both the parent and child objects have a method called
- \var{Doit}. Consider now the following declarations and calls :
- \begin{verbatim}
- Var ParentA,ParentB : PParent;
- Child : PChild;
- ParentA := New(PParent,Init);
- ParentB := New(PChild,Init);
- Child := New(PChild,Init);
- ParentA^.Doit;
- ParentB^.Doit;
- Child^.Doit;
- \end{verbatim}
- First of all, Line 3 will generate a compiler error, stating that one cannot
- generate instances of objects with abstract methods: The compiler has
- detected that \var{PParent} points to an object which has an abstract
- method. Commenting line 3 would allow compilation of the program.
- \begin{remark}
- If an abstract method is overridden, The parent method cannot be called
- with \var{inherited}, since there is no parent method; The compiler
- will detect this, and complain about it, like this:
- \begin{verbatim}
- testo.pp(32,3) Error: Abstract methods can't be called directly
- \end{verbatim}
- If, through some mechanism, an abstract method is called at run-time,
- then a run-time error will occur. (run-time error 211, to be precise)
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Visibility
- \section{Visibility}
- For objects, 3 visibility specifiers exist : \var{private}, \var{protected} and
- \var{public}. If a visibility specifier is not specified, \var{public}
- is assumed.
- Both methods and fields can be hidden from a programmer by putting them
- in a \var{private} section. The exact visibility rule is as follows:
- \begin{description}
- \item [Private\ ] All fields and methods that are in a \var{private} block,
- can only be accessed in the module (i.e. unit or program) that contains
- the object definition.
- They can be accessed from inside the object's methods or from outside them
- e.g. from other objects' methods, or global functions.
- \item [Protected\ ] Is the same as \var{Private}, except that the members of
- a \var{Protected} section are also accessible to descendent types, even if
- they are implemented in other modules.
- \item [Public\ ] sections are always accessible, from everywhere.
- Fields and metods in a \var{public} section behave as though they were part
- of an ordinary \var{record} type.
- \end{description}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Classes
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Classes}
- \label{ch:Classes}
- In the Delphi approach to Object Oriented Programming, everything revolves
- around the concept of 'Classes'. A class can be seen as a pointer to an
- object, or a pointer to a record.
- \begin{remark}
- In earlier versions of \fpc it was necessary, in order to use classes,
- to put the \file{objpas} unit in the uses clause of a unit or program.
- {\em This is no longer needed} as of version 0.99.12. As of version 0.99.12
- the \file{system} unit contains the basic definitions of \var{TObject}
- and \var{TClass}, as well as some auxiliary methods for using classes.
- The \file{objpas} unit still exists, and contains some redefinitions of
- basic types, so they coincide with Delphi types. The unit will be loaded
- automatically when the \var{-S2} or \var{-Sd} options are specified.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Class definitions
- \section{Class definitions}
- The prototype declaration of a class is as follows :
- \input{syntax/typeclas.syn}
- As many \var{private}, \var{protected}, \var{published}
- and \var{public} blocks as needed can be repeated.
- Methods are normal function or procedure declarations.
- As can be seen, the declaration of a class is almost identical to the
- declaration of an object. The real difference between objects and classes
- is in the way they are created (see further in this chapter).
- The visibility of the different sections is as follows:
- \begin{description}
- \item [Private\ ] All fields and methods that are in a \var{private} block, can
- only be accessed in the module (i.e. unit) that contains the class definition.
- They can be accessed from inside the classes' methods or from outside them
- (e.g. from other classes' methods)
- \item [Protected\ ] Is the same as \var{Private}, except that the members of
- a \var{Protected} section are also accessible to descendent types, even if
- they are implemented in other modules.
- \item [Public\ ] sections are always accessible.
- \item [Published\ ] Is the same as a \var{Public} section, but the compiler
- generates also type information that is needed for automatic streaming of
- these classes. Fields defined in a \var{published} section must be of class type.
- Array peroperties cannot be in a \var{published} section.
- \end{description}
- It is also possible to define class reference types:
- \input{syntax/classref.syn}
- Class reference types are used to create instances of a certain class, which
- is not yet known at compile time, but which is specified at run time.
- Essentially, a variable of a class reference type contains a pointer to the
- VMT of the speficied class. This can be used to construct an instance of the
- class corresponding to the VMT. The following example shows how it works:
- \begin{verbatim}
- Type
- TComponentClass = Class of TComponent;
- Function CreateComponent(AClass : TComponentClass; AOwner : TComponent) : TComponent;
- begin
- // ...
- Result:=AClass.Create(AOwner);
- // ...
- end;
- \end{verbatim}
- More about instantiating a class can be found in the next section.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Class instantiation
- \section{Class instantiation}
- Classes must be created using their constructor. Remember that a class is a
- pointer to an object, so when a variable of some class is declared, the
- compiler just allocates a pointer, not the entire object. The constructor of
- a class returns a pointer to an initialized instance of the object.
- So, to initialize an instance of some class, one would do the following :
- \begin{verbatim}
- ClassVar := ClassType.ConstructorName;
- \end{verbatim}
- The extended syntax of \var{new} and \var{dispose} can be used to
- instantiate and destroy class instances.
- That construct is reserved for use with objects only.
- Calling the constructor will provoke a call to \var{getmem}, to allocate
- enough space to hold the class instance data.
- After that, the constuctor's code is executed.
- The constructor has a pointer to it's data, in \var{self}.
- \begin{remark}
- \begin{itemize}
- \item The \var{\{\$PackRecords \}} directive also affects classes.
- i.e. the alignment in memory of the different fields depends on the
- value of the \var{\{\$PackRecords \}} directive.
- \item Just as for objects and records, a packed class can be declared.
- This has the same effect as on an object, or record, namely that the
- elements are aligned on 1-byte boundaries. i.e. as close as possible.
- \item \var{SizeOf(class)} will return 4, since a class is but a pointer to
- an object. To get the size of the class instance data, use the
- \var{TObject.InstanceSize} method.
- \end{itemize}
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Methods
- \section{Methods}
- \subsection{invocation}
- Method invocation for classes is no different than for objects. The
- following is a valid method invocation:
- \begin{verbatim}
- Var AnObject : TAnObject;
- begin
- AnObject := TAnObject.Create;
- ANobject.AMethod;
- \end{verbatim}
- \subsection{Virtual methods}
- Classes have virtual methods, just as objects do. There is however a
- difference between the two. For objects, it is sufficient to redeclare the
- same method in a descendent object with the keyword \var{virtual} to
- override it. For classes, the situation is different:
- virtual methods {\em must} be overridden with the \var{override} keyword. Failing to do so,
- will start a {\em new} batch of virtual methods, hiding the previous
- one. The \var{Inherited} keyword will not jump to the inherited method, if
- virtual was used.
- The following code is {\em wrong}:
- \begin{verbatim}
- Type
- ObjParent = Class
- Procedure MyProc; virtual;
- end;
- ObjChild = Class(ObjPArent)
- Procedure MyProc; virtual;
- end;
- \end{verbatim}
- The compiler will produce a warning:
- \begin{verbatim}
- Warning: An inherited method is hidden by OBJCHILD.MYPROC
- \end{verbatim}
- The compiler will compile it, but using \var{Inherited} can
- produce strange effects.
- The correct declaration is as follows:
- \begin{verbatim}
- Type ObjParent = Class
- Procedure MyProc; virtual;
- end;
- ObjChild = Class(ObjPArent)
- Procedure MyProc; override;
- end;
- \end{verbatim}
- This will compile and run without warnings or errors.
- \subsection{Message methods}
- New in classes are \var{message} methods. Pointers to message methods are
- stored in a special table, together with the integer or string cnstant that
- they were declared with. They are primarily intended to ease programming of
- callback functions in several \var{GUI} toolkits, such as \var{Win32} or
- \var{GTK}. In difference with Delphi, \fpc also accepts strings as message
- identifiers.
- Message methods that are declared with an integer constant can take only one
- var argument (typed or not):
- \begin{verbatim}
- Procedure TMyObject.MyHandler(Var Msg); Message 1;
- \end{verbatim}
- The method implementation of a message function is no different from an
- ordinary method. It is also possible to call a message method directly,
- but this should not be done. Instead, the \var{TObject.Dispatch} method
- should be used.
- The \var{TOBject.Dispatch} method can be used to call a \var{message}
- handler. It is declared in the \file{system} unit and will accept a var
- parameter which must have at the first position a cardinal with the
- message ID that should be called. For example:
- \begin{verbatim}
- Type
- TMsg = Record
- MSGID : Cardinal
- Data : Pointer;
- Var
- Msg : TMSg;
- MyObject.Dispatch (Msg);
- \end{verbatim}
- In this example, the \var{Dispatch} method will look at the object and all
- it's ancestors (starting at the object, and searching up the class tree),
- to see if a message method with message \var{MSGID} has been
- declared. If such a method is found, it is called, and passed the
- \var{Msg} parameter.
- If no such method is found, \var{DefaultHandler} is called.
- \var{DefaultHandler} is a virtual method of \var{TObject} that doesn't do
- anything, but which can be overridden to provide any processing that might be
- needed. \var{DefaultHandler} is declared as follows:
- \begin{verbatim}
- procedure defaulthandler(var message);virtual;
- \end{verbatim}
- In addition to the message method with a \var{Integer} identifier,
- \fpc also supports a message method with a string identifier:
- \begin{verbatim}
- Procedure TMyObject.MyStrHandler(Var Msg); Message 'OnClick';
- \end{verbatim}
- The working of the string message handler is the same as the ordinary
- integer message handler:
- The \var{TOBject.DispatchStr} method can be used to call a \var{message}
- handler. It is declared in the system unit and will accept one parameter
- which must have at the first position a string with the message ID that
- should be called. For example:
- \begin{verbatim}
- Type
- TMsg = Record
- MsgStr : String[10]; // Arbitrary length up to 255 characters.
- Data : Pointer;
- Var
- Msg : TMSg;
- MyObject.DispatchStr (Msg);
- \end{verbatim}
- In this example, the \var{DispatchStr} method will look at the object and
- all it's ancestors (starting at the object, and searching up the class tree),
- to see if a message method with message \var{MsgStr} has been
- declared. If such a method is found, it is called, and passed the
- \var{Msg} parameter.
- If no such method is found, \var{DefaultHandlerStr} is called.
- \var{DefaultHandlerStr} is a virtual method of \var{TObject} that doesn't do
- anything, but which can be overridden to provide any processing that might be
- needed. \var{DefaultHandlerStr} is declared as follows:
- \begin{verbatim}
- procedure DefaultHandlerStr(var message);virtual;
- \end{verbatim}
- In addition to this mechanism, a string message method accepts a \var{self}
- parameter:
- \begin{verbatim}
- TMyObject.StrMsgHandler(Data : Pointer; Self : TMyObject);Message 'OnClick';
- \end{verbatim}
- When encountering such a method, the compiler will generate code that loads
- the \var{Self} parameter into the object instance pointer. The result of
- this is that it is possible to pass \var{Self} as a parameter to such a
- method.
- \begin{remark}
- The type of the \var{Self} parameter must be of the same class
- as the class the method is defined in.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Properties
- \section{Properties}
- Classes can contain properties as part of their fields list. A property
- acts like a normal field, i.e. its value can be retrieved or set, but it
- allows to redirect the access of the field through functions and
- procedures. They provide a means to associate an action with an assignment
- of or a reading from a class 'field'. This allows for e.g. checking that a
- value is valid when assigning, or, when reading, it allows to construct the
- value on the fly. Moreover, properties can be read-only or write only.
- The prototype declaration of a property is as follows:
- \input{syntax/property.syn}
- A \var{read specifier} is either the name of a field that contains the
- property, or the name of a method function that has the same return type as
- the property type. In the case of a simple type, this
- function must not accept an argument. A \var{read specifier} is optional,
- making the property write-only.
- A \var{write specifier} is optional: If there is no \var{write specifier}, the
- property is read-only. A write specifier is either the name of a field, or
- the name of a method procedure that accepts as a sole argument a variable of
- the same type as the property.
- The section (\var{private}, \var{published}) in which the specified function or
- procedure resides is irrelevant. Usually, however, this will be a protected
- or private method.
- Example:
- Given the following declaration:
- \begin{verbatim}
- Type
- MyClass = Class
- Private
- Field1 : Longint;
- Field2 : Longint;
- Field3 : Longint;
- Procedure Sety (value : Longint);
- Function Gety : Longint;
- Function Getz : Longint;
- Public
- Property X : Longint Read Field1 write Field2;
- Property Y : Longint Read GetY Write Sety;
- Property Z : Longint Read GetZ;
- end;
- Var MyClass : TMyClass;
- \end{verbatim}
- The following are valid statements:
- \begin{verbatim}
- WriteLn ('X : ',MyClass.X);
- WriteLn ('Y : ',MyClass.Y);
- WriteLn ('Z : ',MyClass.Z);
- MyClass.X := 0;
- MyClass.Y := 0;
- \end{verbatim}
- But the following would generate an error:
- \begin{verbatim}
- MyClass.Z := 0;
- \end{verbatim}
- because Z is a read-only property.
- What happens in the above statements is that when a value needs to be read,
- the compiler inserts a call to the various \var{getNNN} methods of the
- object, and the result of this call is used. When an assignment is made,
- the compiler passes the value that must be assigned as a paramater to
- the various \var{setNNN} methods.
- Because of this mechanism, properties cannot be passed as var arguments to a
- function or procedure, since there is no known address of the property (at
- least, not always).
- If the property definition contains an index, then the read and write
- specifiers must be a function and a procedure. Moreover, these functions
- require an additional parameter : An integer parameter. This allows to read
- or write several properties with the same function. For this, the properties
- must have the same type.
- The following is an example of a property with an index:
- \begin{verbatim}
- {$mode objfpc}
- Type TPoint = Class(TObject)
- Private
- FX,FY : Longint;
- Function GetCoord (Index : Integer): Longint;
- Procedure SetCoord (Index : Integer; Value : longint);
- Public
- Property X : Longint index 1 read GetCoord Write SetCoord;
- Property Y : Longint index 2 read GetCoord Write SetCoord;
- Property Coords[Index : Integer]:Longint Read GetCoord;
- end;
- Procedure TPoint.SetCoord (Index : Integer; Value : Longint);
- begin
- Case Index of
- 1 : FX := Value;
- 2 : FY := Value;
- end;
- end;
- Function TPoint.GetCoord (INdex : Integer) : Longint;
- begin
- Case Index of
- 1 : Result := FX;
- 2 : Result := FY;
- end;
- end;
- Var P : TPoint;
- begin
- P := TPoint.create;
- P.X := 2;
- P.Y := 3;
- With P do
- WriteLn ('X=',X,' Y=',Y);
- end.
- \end{verbatim}
- When the compiler encounters an assignment to \var{X}, then \var{SetCoord}
- is called with as first parameter the index (1 in the above case) and with
- as a second parameter the value to be set.
- Conversely, when reading the value of \var{X}, the compiler calls
- \var{GetCoord} and passes it index 1.
- Indexes can only be integer values.
- Array propertie also exist. These are properties that accept an
- index, just as an array does. Only now the index doesn't have to be an
- ordinal type, but can be any type.
- A \var{read specifier} for an array property is the name method function
- that has the same return type as the property type.
- The function must accept as a sole arguent a variable of the same type as
- the index type. For an array property, one cannot specify fields as \var{read
- specifiers}.
- A \var{write specifier} for an array property is the name of a method
- procedure that accepts two arguments: The first argument has the same
- type as the index, and the second argument is a parameter of the same
- type as the property type.
- As an example, see the following declaration:
- \begin{verbatim}
- Type TIntList = Class
- Private
- Function GetInt (I : Longint) : longint;
- Function GetAsString (A : String) : String;
- Procedure SetInt (I : Longint; Value : Longint;);
- Procedure SetAsString (A : String; Value : String);
- Public
- Property Items [i : Longint] : Longint Read GetInt
- Write SetInt;
- Property StrItems [S : String] : String Read GetAsString
- Write SetAsstring;
- end;
- Var AIntList : TIntList;
- \end{verbatim}
- Then the following statements would be valid:
- \begin{verbatim}
- AIntList.Items[26] := 1;
- AIntList.StrItems['twenty-five'] := 'zero';
- WriteLn ('Item 26 : ',AIntList.Items[26]);
- WriteLn ('Item 25 : ',AIntList.StrItems['twenty-five']);
- \end{verbatim}
- While the following statements would generate errors:
- \begin{verbatim}
- AIntList.Items['twenty-five'] := 1;
- AIntList.StrItems[26] := 'zero';
- \end{verbatim}
- Because the index types are wrong.
- Array properties can be declared as \var{default} properties. This means that
- it is not necessary to specify the property name when assigning or reading
- it. If, in the previous example, the definition of the items property would
- have been
- \begin{verbatim}
- Property Items[i : Longint]: Longint Read GetInt
- Write SetInt; Default;
- \end{verbatim}
- Then the assignment
- \begin{verbatim}
- AIntList.Items[26] := 1;
- \end{verbatim}
- Would be equivalent to the following abbreviation.
- \begin{verbatim}
- AIntList[26] := 1;
- \end{verbatim}
- Only one default property per class is allowed, and descendent classes
- cannot redeclare the default property.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Interfaces
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Interfaces}
- \label{ch:Interfaces}
- \section{Definition}
- As of version 1.1, FPC supports interfaces. Interfaces are an
- alternative to multiple inheritance (where a class can have multiple
- parent classes) as implemented for instance in C++. An interface is
- basically a named set of methods and properties: A class that
- {\em implements} the interface provides {\em all} the methods as
- they are enumerated in the Interface definition. It is not possible for a
- class to implement only part of the interface: it is all or nothing.
- Interfaces can also be ordered in a hierarchy, exactly as classes:
- An interface definition that inherits from another interface definition
- contains all the methods from the parent interface, as well as the methods
- explicitly named in the interface definition. A class implementing an
- interface must then implement all members of the interface as well as the
- methods of the parent interface(s).
- An interface can be uniquely identified by a GUID (GUID is an acronym for
- Globally Unique Identifier, a 128-bit integer guaranteed always to be
- unique\footnote{In theory, of course.}. Especially on Windows systems, the
- GUID of an interface can and must be used when using COM.
- The definition of an Interface has the following form:
- \input{syntax/typeintf.syn}
- Along with this definition the following must be noted:
- \begin{itemize}
- \item Interfaces can only be used in \var{DELPHI} mode or in \var{OBJFPC}
- mode.
- \item There are no visibility specifiers. All members are public (indeed,
- it would make little sense to make them private or protected).
- \item The properties declared in an interface can only have methods as read and
- write specifiers.
- \item There are no constructors or destructors. Instances of interfaces
- cannot be created directly: instead, an instance of a class implementing
- the interface must be created.
- \item Only calling convention modifiers may be present in the definition of
- a method. Modifiers as \var{virtual}, \var{abstract} or \var{dynamic}, and
- hence also \var{override} cannot be present in the definition of a interface
- definition.
- \end{itemize}
- \section{Interface identification: A GUID}
- An interface can be identified by a GUID. This is a 128-bit number, which is
- represented in a text representation (a string literal):
- \begin{verbatim}
- ['{HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH}']
- \end{verbatim}
- Each \var{H} character represents a hexadecimal number (0-9,A-F). The format
- contains 8-4-4-4-12 numbers. A GUID can also be represented by the following
- record, defined in the \file{objpas} unit (included automatically when in
- \var{DELPHI} or \var{OBJFPC} mode:
- \begin{verbatim}
- PGuid = ^TGuid;
- TGuid = packed record
- case integer of
- 1 : (
- Data1 : DWord;
- Data2 : word;
- Data3 : word;
- Data4 : array[0..7] of byte;
- );
- 2 : (
- D1 : DWord;
- D2 : word;
- D3 : word;
- D4 : array[0..7] of byte;
- );
- end;
- \end{verbatim}
- A constant of type TGUID can be specified using a string literal:
- \begin{verbatim}
- {$mode objfpc}
- program testuid;
- Const
- MyGUID : TGUID = '{10101010-1010-0101-1001-110110110110}';
- begin
- end.
- \end{verbatim}
- Normally, the GUIDs are only used in Windows, when using COM interfaces.
- More on this in the next section.
- \section{Interfaces and COM}
- When using interfaces on Windows which should be available to the COM
- subsystem, the calling convention should be \var{stdcall} - this is not the
- default \fpc calling convention, so it should be specified explicitly.
- COM does not know properties. It only knows methods. So when specifying
- property definitions as part of an interface definition, be aware that the
- properties will only be known in the \fpc compiled program: other Windows
- programs will not be aware of the property definitions. For this reason,
- property definitions must always have interface methods as the read/write
- specifiers.
- \section*{Interface implementations}
- When a class implements an interface, it should implement all methods of the
- interface. If a method of an interface is not implemented, then the compiler
- will give an error. For example:
- \begin{verbatim}
- Type
- IMyInterface = Interface
- Function MyFunc : Integer;
- Function MySecondFunc : Integer;
- end;
- TMyClass = Class(TInterfacedObject,IMyInterface)
- Function MyFunc : Integer;
- Function MyOtherFunc : Integer;
- end;
- Function TMyClass.MyFunc : Integer;
- begin
- Result:=23;
- end;
- Function TMyClass.MyOtherFunc : Integer;
- begin
- Result:=24;
- end;
- \end{verbatim}
- will result in a compiler error:
- \begin{verbatim}
- Error: No matching implementation for interface method
- "IMyInterface.MySecondFunc:LongInt" found
- \end{verbatim}
- At the moment of writing, the compiler does not yet support providing
- aliases for an interface as in Delphi. i.e. the following will not yet
- compile:
- \begin{verbatim}
- ype
- IMyInterface = Interface
- Function MyFunc : Integer;
- end;
- TMyClass = Class(TInterfacedObject,IMyInterface)
- Function MyOtherFunction : Integer;
- // The following fails in FPC.
- Function IMyInterface.MyFunc = MyOtherFunction;
- end;
- \end{verbatim}
- This declaration should tell the compiler that the \var{MyFunc} method of
- the \var{IMyInterface} interface is implemented in the \var{MyOtherFunction}
- method of the \var{TMyClass} class.
- \section{CORBA and other Interfaces}
- COM is not the only architecture where interfaces are used. CORBA knows
- interfaces, UNO (the OpenOffice API) uses interfaces, and Java as well.
- These languages do not know the \var{IUnknown} interface used as the basis of
- all interfaces in COM. It would therefore be a bad idea if an interface
- automatically descended from \var{IUnknown} if no parent interface was
- specified. Therefore, a directive \var{\{\$INTERFACES\}} was introduced in
- \fpc: it specifies what the parent interface is of an interface, declared
- without parent. More information about this directive can be found in the
- \progref.
- Note that COM interfaces are by default reference counted.
- CORBA interfaces are not necessarily reference counted.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Expressions
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Expressions}
- \label{ch:Expressions}
- Expressions occur in assignments or in tests. Expressions produce a value,
- of a certain type.
- Expressions are built with two components: Operators and their operands.
- Usually an operator is binary, i.e. it requires 2 operands. Binary operators
- occur always between the operands (as in \var{X/Y}). Sometimes an
- operator is unary, i.e. it requires only one argument. A unary operator
- occurs always before the operand, as in \var{-X}.
- When using multiple operands in an expression, the precedence rules of
- \seet{OperatorPrecedence} are used.
- \begin{FPCltable}{lll}{Precedence of operators}{OperatorPrecedence}
- Operator & Precedence & Category \\ \hline
- \var{Not, @} & Highest (first) & Unary operators\\
- \var{* / div mod and shl shr as} & Second & Multiplying operators\\
- \var{+ - or xor} & Third & Adding operators \\
- \var{< <> < > <= >= in is} & Lowest (Last) & relational operators \\
- \hline
- \end{FPCltable}
- When determining the precedence, the compiler uses the following rules:
- \begin{enumerate}
- \item In operations with unequal precedences the operands belong to the
- operater with the highest precedence. For example, in \var{5*3+7}, the
- multiplication is higher in precedence than the addition, so it is
- executed first. The result would be 22.
- \item If parentheses are used in an expression, their contents is evaluated
- first. Thus, \var {5*(3+7)} would result in 50.
- \end{enumerate}
- \begin{remark}
- The order in which expressions of the same precedence are evaluated is not
- guaranteed to be left-to-right. In general, no assumptions on which expression
- is evaluated first should be made in such a case.
- The compiler will decide which expression to evaluate first based on
- optimization rules. Thus, in the following expression:
- \begin{verbatim}
- a := g(3) + f(2);
- \end{verbatim}
- \var{f(2)} may be executed before \var{g(3)}. This behaviour is distinctly
- different from \delphi or \tp.
- If one expression {\em must} be executed before the other, it is necessary
- to split up the statement using temporary results:
- \begin{verbatim}
- e1 := g(3);
- a := e1 + f(2);
- \end{verbatim}
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Expression syntax
- \section{Expression syntax}
- An expression applies relational operators to simple expressions. Simple
- expressions are a series of terms (what a term is, is explained below), joined by
- adding operators.
- \input{syntax/expsimpl.syn}
- The following are valid expressions:
- \begin{verbatim}
- GraphResult<>grError
- (DoItToday=Yes) and (DoItTomorrow=No);
- Day in Weekend
- \end{verbatim}
- And here are some simple expressions:
- \begin{verbatim}
- A + B
- -Pi
- ToBe or NotToBe
- \end{verbatim}
- Terms consist of factors, connected by multiplication operators.
- \input{syntax/expterm.syn}
- Here are some valid terms:
- \begin{verbatim}
- 2 * Pi
- A Div B
- (DoItToday=Yes) and (DoItTomorrow=No);
- \end{verbatim}
- Factors are all other constructions:
- \input{syntax/expfact.syn}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Function calls
- \section{Function calls}
- Function calls are part of expressions (although, using extended syntax,
- they can be statements too). They are constructed as follows:
- \input{syntax/fcall.syn}
- The \synt{variable reference} must be a procedural type variable reference.
- A method designator can only be used inside the method of an object. A
- qualified method designator can be used outside object methods too.
- The function that will get called is the function with a declared parameter
- list that matches the actual parameter list. This means that
- \begin{enumerate}
- \item The number of actual parameters must equal the number of declared
- parameters (unless default parameter values are used).
- \item The types of the parameters must be compatible. For variable
- reference parameters, the parameter types must be exactly the same.
- \end{enumerate}
- If no matching function is found, then the compiler will generate an error.
- Depending on the fact of the function is overloaded (i.e. multiple functions
- with the same name, but different parameter lists) the error will be
- different.
- There are cases when the compiler will not execute the function call in an
- expression. This is the case when assigning a value to a procedural
- type variable, as in the following example:
- \begin{verbatim}
- Type
- FuncType = Function: Integer;
- Var A : Integer;
- Function AddOne : Integer;
- begin
- A := A+1;
- AddOne := A;
- end;
- Var F : FuncType;
- N : Integer;
- begin
- A := 0;
- F := AddOne; { Assign AddOne to F, Don't call AddOne}
- N := AddOne; { N := 1 !!}
- end.
- \end{verbatim}
- In the above listing, the assigment to F will not cause the function AddOne
- to be called. The assignment to N, however, will call AddOne.
- A problem with this syntax is the following construction:
- \begin{verbatim}
- If F = AddOne Then
- DoSomethingHorrible;
- \end{verbatim}
- Should the compiler compare the addresses of \var{F} and \var{AddOne},
- or should it call both functions, and compare the result ? \fpc solves this
- by deciding that a procedural variable is equivalent to a pointer. Thus the
- compiler will give a type mismatch error, since AddOne is considered a
- call to a function with integer result, and F is a pointer, Hence a type
- mismatch occurs.
- How then, should one compare whether \var{F} points to the function
- \var{AddOne} ? To do this, one should use the address operator \var{@}:
- \begin{verbatim}
- If F = @AddOne Then
- WriteLn ('Functions are equal');
- \end{verbatim}
- The left hand side of the boolean expression is an address. The right hand
- side also, and so the compiler compares 2 addresses.
- How to compare the values that both functions return ? By adding an empty
- parameter list:
- \begin{verbatim}
- If F()=Addone then
- WriteLn ('Functions return same values ');
- \end{verbatim}
- Remark that this behaviour is not compatible with Delphi syntax.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Set constructors
- \section{Set constructors}
- When a set-type constant must be entered in an expression, a
- set constructor must be given. In essence this is the same thing as when a
- type is defined, only there is no identifier to identify the set with.
- A set constructor is a comma separated list of expressions, enclosed in
- square brackets.
- \input{syntax/setconst.syn}
- All set groups and set elements must be of the same ordinal type.
- The empty set is denoted by \var{[]}, and it can be assigned to any type of
- set. A set group with a range \var{[A..Z]} makes all values in the range a
- set element. If the first range specifier has a bigger ordinal value than
- the second the set is empty, e.g., \var{[Z..A]} denotes an empty set.
- The following are valid set constructors:
- \begin{verbatim}
- [today,tomorrow]
- [Monday..Friday,Sunday]
- [ 2, 3*2, 6*2, 9*2 ]
- ['A'..'Z','a'..'z','0'..'9']
- \end{verbatim}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Value typecasts
- \section{Value typecasts}
- Sometimes it is necessary to change the type of an expression, or a part of
- the expression, to be able to be assignment compatible. This is done through
- a value typecast. The syntax diagram for a value typecast is as follows:
- \input{syntax/tcast.syn}
- Value typecasts cannot be used on the left side of assignments, as variable
- typecasts.
- Here are some valid typecasts:
- \begin{verbatim}
- Byte('A')
- Char(48)
- boolean(1)
- longint(@Buffer)
- \end{verbatim}
- The type size of the expression and the size of the type cast must be the
- same. That is, the following doesn't work:
- \begin{verbatim}
- Integer('A')
- Char(4875)
- boolean(100)
- Word(@Buffer)
- \end{verbatim}
- This is different from Delphi or Turbo Pascal behaviour.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The @ operator
- \section{The @ operator}
- The address operator \var{@} returns the address of a variable, procedure
- or function. It is used as follows:
- \input{syntax/address.syn}
- The \var{@} operator returns a typed pointer if the \var{\$T} switch is on.
- If the \var{\$T} switch is off then the address operator returns an untyped
- pointer, which is assigment compatible with all pointer types. The type of
- the pointer is \var{\^{}T}, where \var{T} is the type of the variable
- reference.
- For example, the following will compile
- \begin{verbatim}
- Program tcast;
- {$T-} { @ returns untyped pointer }
- Type art = Array[1..100] of byte;
- Var Buffer : longint;
- PLargeBuffer : ^art;
- begin
- PLargeBuffer := @Buffer;
- end.
- \end{verbatim}
- Changing the \var{\{\$T-\}} to \var{\{\$T+\}} will prevent the compiler from
- compiling this. It will give a type mismatch error.
- By default, the address operator returns an untyped pointer.
- Applying the address operator to a function, method, or procedure identifier
- will give a pointer to the entry point of that function. The result is an
- untyped pointer.
- By default, the address operator must be used if a value must be assigned
- to a procedural type variable. This behaviour can be avoided by using the
- \var{-So} or \var{-S2} switches, which result in a more compatible Delphi or
- Turbo Pascal syntax.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Operators
- \section{Operators}
- Operators can be classified according to the type of expression they
- operate on. We will discuss them type by type.
- \subsection{Arithmetic operators}
- Arithmetic operators occur in arithmetic operations, i.e. in expressions
- that contain integers or reals. There are 2 kinds of operators : Binary and
- unary arithmetic operators.
- Binary operators are listed in \seet{binaroperators}, unary operators are
- listed in \seet{unaroperators}.
- \begin{FPCltable}{ll}{Binary arithmetic operators}{binaroperators}
- Operator & Operation \\ \hline
- \var{+} & Addition\\
- \var{-} & Subtraction\\
- \var{*} & Multiplication \\
- \var{/} & Division \\
- \var{Div} & Integer division \\
- \var{Mod} & Remainder \\ \hline
- \end{FPCltable}
- With the exception of \var{Div} and \var{Mod}, which accept only integer
- expressions as operands, all operators accept real and integer expressions as
- operands.
- For binary operators, the result type will be integer if both operands are
- integer type expressions. If one of the operands is a real type expression,
- then the result is real.
- As an exception : division (\var{/}) results always in real values.
- \begin{FPCltable}{ll}{Unary arithmetic operators}{unaroperators}
- Operator & Operation \\ \hline
- \var{+} & Sign identity\\
- \var{-} & Sign inversion \\ \hline
- \end{FPCltable}
- For unary operators, the result type is always equal to the expression type.
- The division (\var{/}) and \var{Mod} operator will cause run-time errors if
- the second argument is zero.
- The sign of the result of a \var{Mod} operator is the same as the sign of
- the left side operand of the \var{Mod} operator. In fact, the \var{Mod}
- operator is equivalent to the following operation :
- \begin{verbatim}
- I mod J = I - (I div J) * J
- \end{verbatim}
- but it executes faster than the right hand side expression.
- \subsection{Logical operators}
- Logical operators act on the individual bits of ordinal expressions.
- Logical operators require operands that are of an integer type, and produce
- an integer type result. The possible logical operators are listed in
- \seet{logicoperations}.
- \begin{FPCltable}{ll}{Logical operators}{logicoperations}
- Operator & Operation \\ \hline
- \var{not} & Bitwise negation (unary) \\
- \var{and} & Bitwise and \\
- \var{or} & Bitwise or \\
- \var{xor} & Bitwise xor \\
- \var{shl} & Bitwise shift to the left \\
- \var{shr} & Bitwise shift to the right \\ \hline
- \end{FPCltable}
- The following are valid logical expressions:
- \begin{verbatim}
- A shr 1 { same as A div 2, but faster}
- Not 1 { equals -2 }
- Not 0 { equals -1 }
- Not -1 { equals 0 }
- B shl 2 { same as B * 4 for integers }
- 1 or 2 { equals 3 }
- 3 xor 1 { equals 2 }
- \end{verbatim}
- \subsection{Boolean operators}
- Boolean operators can be considered logical operations on a type with 1 bit
- size. Therefore the \var{shl} and \var{shr} operations have little sense.
- Boolean operators can only have boolean type operands, and the resulting
- type is always boolean. The possible operators are listed in
- \seet{booleanoperators}
- \begin{FPCltable}{ll}{Boolean operators}{booleanoperators}
- Operator & Operation \\ \hline
- \var{not} & logical negation (unary) \\
- \var{and} & logical and \\
- \var{or} & logical or \\
- \var{xor} & logical xor \\ \hline
- \end{FPCltable}
- \begin{remark} Boolean expressions are always evaluated with short-circuit
- evaluation. This means that from the moment the result of the complete
- expression is known, evaluation is stopped and the result is returned.
- For instance, in the following expression:
- \begin{verbatim}
- B := True or MaybeTrue;
- \end{verbatim}
- The compiler will never look at the value of \var{MaybeTrue}, since it is
- obvious that the expression will always be true. As a result of this
- strategy, if \var{MaybeTrue} is a function, it will not get called !
- (This can have surprising effects when used in conjunction with properties)
- \end{remark}
- \subsection{String operators}
- There is only one string operator : \var{+}. It's action is to concatenate
- the contents of the two strings (or characters) it stands between.
- One cannot use \var{+} to concatenate null-terminated (\var{PChar}) strings.
- The following are valid string operations:
- \begin{verbatim}
- 'This is ' + 'VERY ' + 'easy !'
- Dirname+'\'
- \end{verbatim}
- The following is not:
- \begin{verbatim}
- Var Dirname = Pchar;
- ...
- Dirname := Dirname+'\';
- \end{verbatim}
- Because \var{Dirname} is a null-terminated string.
- \subsection{Set operators}
- The following operations on sets can be performed with operators:
- Union, difference and intersection. The operators needed for this are listed
- in \seet{setoperators}.
- \begin{FPCltable}{ll}{Set operators}{setoperators}
- Operator & Action \\ \hline
- \var{+} & Union \\
- \var{-} & Difference \\
- \var{*} & Intersection \\ \hline
- \end{FPCltable}
- The set type of the operands must be the same, or an error will be
- generated by the compiler.
- \subsection{Relational operators}
- The relational operators are listed in \seet{relationoperators}
- \begin{FPCltable}{ll}{Relational operators}{relationoperators}
- Operator & Action \\ \hline
- \var{=} & Equal \\
- \var{<>} & Not equal \\
- \var{<} & Stricty less than\\
- \var{>} & Strictly greater than\\
- \var{<=} & Less than or equal \\
- \var{>=} & Greater than or equal \\
- \var{in} & Element of \\ \hline
- \end{FPCltable}
- Left and right operands must be of the same type. Only integer
- and real types can be mixed in relational expressions.
- Comparing strings is done on the basis of their ASCII code representation.
- When comparing pointers, the addresses to which they point are compared.
- This also is true for \var{PChar} type pointers. To compare the strings
- the \var{Pchar} point to, the \var{StrComp} function
- from the \file{strings} unit must be used.
- The \var{in} returns \var{True} if the left operand (which must have the same
- ordinal type as the set type, and which must be in the range 0..255) is an
- element of the set which is the right operand, otherwise it returns \var{False}
- \chapter{Statements}
- \label{ch:Statements}
- The heart of each algorithm are the actions it takes. These actions are
- contained in the statements of a program or unit. Each statement can be
- labeled and jumped to (within certain limits) with \var{Goto} statements.
- This can be seen in the following syntax diagram:
- \input{syntax/statement.syn}
- A label can be an identifier or an integer digit.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Simple statements
- \section{Simple statements}
- A simple statement cannot be decomposed in separate statements. There are
- basically 4 kinds of simple statements:
- \input{syntax/simstate.syn}
- Of these statements, the {\em raise statement} will be explained in the
- chapter on Exceptions (\seec{Exceptions})
- \subsection{Assignments}
- Assignments give a value to a variable, replacing any previous value the
- variable might have had:
- \input{syntax/assign.syn}
- In addition to the standard Pascal assignment operator (\var{ := }), which
- simply replaces the value of the varable with the value resulting from the
- expression on the right of the { := } operator, \fpc
- supports some c-style constructions. All available constructs are listed in
- \seet{assignments}.
- \begin{FPCltable}{lr}{Allowed C constructs in \fpc}{assignments}
- Assignment & Result \\ \hline
- a += b & Adds \var{b} to \var{a}, and stores the result in \var{a}.\\
- a -= b & Substracts \var{b} from \var{a}, and stores the result in
- \var{a}. \\
- a *= b & Multiplies \var{a} with \var{b}, and stores the result in
- \var{a}. \\
- a /= b & Divides \var{a} through \var{b}, and stores the result in
- \var{a}. \\ \hline
- \end{FPCltable}
- For these constructs to work, the \var{-Sc} command-line switch must
- be specified.
- \begin{remark}
- These constructions are just for typing convenience, they
- don't generate different code.
- Here are some examples of valid assignment statements:
- \begin{verbatim}
- X := X+Y;
- X+=Y; { Same as X := X+Y, needs -Sc command line switch}
- X/=2; { Same as X := X/2, needs -Sc command line switch}
- Done := False;
- Weather := Good;
- MyPi := 4* Tan(1);
- \end{verbatim}
- \end{remark}
- \subsection{Procedure statements}
- Procedure statements are calls to subroutines. There are
- different possibilities for procedure calls: A normal procedure call, an
- object method call (fully qualified or not), or even a call to a procedural
- type variable. All types are present in the following diagram.
- \input{syntax/procedure.syn}
- The \fpc compiler will look for a procedure with the same name as given in
- the procedure statement, and with a declared parameter list that matches the
- actual parameter list.
- The following are valid procedure statements:
- \begin{verbatim}
- Usage;
- WriteLn('Pascal is an easy language !');
- Doit();
- \end{verbatim}
- \subsection{Goto statements}
- \fpc supports the \var{goto} jump statement. Its prototype syntax is
- \input{syntax/goto.syn}
- When using \var{goto} statements, the following must be kept in mind:
- \begin{enumerate}
- \item The jump label must be defined in the same block as the \var{Goto}
- statement.
- \item Jumping from outside a loop to the inside of a loop or vice versa can
- have strange effects.
- \item To be able to use the \var{Goto} statement, the \var{-Sg} compiler
- switch must be used.
- \end{enumerate}
- \var{Goto} statements are considered bad practice and should be avoided as
- much as possible. It is always possible to replace a \var{goto} statement by a
- construction that doesn't need a \var{goto}, although this construction may
- not be as clear as a goto statement.
- For instance, the following is an allowed goto statement:
- \begin{verbatim}
- label
- jumpto;
- ...
- Jumpto :
- Statement;
- ...
- Goto jumpto;
- ...
- \end{verbatim}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Structured statements
- \section{Structured statements}
- Structured statements can be broken into smaller simple statements, which
- should be executed repeatedly, conditionally or sequentially:
- \input{syntax/struct.syn}
- Conditional statements come in 2 flavours :
- \input{syntax/conditio.syn}
- Repetitive statements come in 3 flavours:
- \input{syntax/repetiti.syn}
- The following sections deal with each of these statements.
- \subsection{Compound statements}
- Compound statements are a group of statements, separated by semicolons,
- that are surrounded by the keywords \var{Begin} and \var{End}. The
- Last statement doesn't need to be followed by a semicolon, although it is
- allowed. A compound statement is a way of grouping statements together,
- executing the statements sequentially. They are treated as one statement
- in cases where Pascal syntax expects 1 statement, such as in
- \var{if ... then} statements.
- \input{syntax/compound.syn}
- \subsection{The \var{Case} statement}
- \fpc supports the \var{case} statement. Its syntax diagram is
- \input{syntax/case.syn}
- The constants appearing in the various case parts must be known at
- compile-time, and can be of the following types : enumeration types,
- Ordinal types (except boolean), and chars. The expression must be also of
- this type, or a compiler error will occur. All case constants must
- have the same type.
- The compiler will evaluate the expression. If one of the case constants
- values matches the value of the expression, the statement that follows
- this constant is executed. After that, the program continues after the final
- \var{end}.
- If none of the case constants match the expression value, the statement
- after the \var{else} keyword is executed. This can be an empty statement.
- If no else part is present, and no case constant matches the expression
- value, program flow continues after the final \var{end}.
- The case statements can be compound statements
- (i.e. a \var{begin..End} block).
- \begin{remark}
- Contrary to Turbo Pascal, duplicate case labels are not
- allowed in \fpc, so the following code will generate an error when
- compiling:
- \begin{verbatim}
- Var i : integer;
- ...
- Case i of
- 3 : DoSomething;
- 1..5 : DoSomethingElse;
- end;
- \end{verbatim}
- The compiler will generate a \var{Duplicate case label} error when compiling
- this, because the 3 also appears (implicitly) in the range \var{1..5}. This
- is similar to Delphi syntax.
- \end{remark}
- The following are valid case statements:
- \begin{verbatim}
- Case C of
- 'a' : WriteLn ('A pressed');
- 'b' : WriteLn ('B pressed');
- 'c' : WriteLn ('C pressed');
- else
- WriteLn ('unknown letter pressed : ',C);
- end;
- \end{verbatim}
- Or
- \begin{verbatim}
- Case C of
- 'a','e','i','o','u' : WriteLn ('vowel pressed');
- 'y' : WriteLn ('This one depends on the language');
- else
- WriteLn ('Consonant pressed');
- end;
- \end{verbatim}
- \begin{verbatim}
- Case Number of
- 1..10 : WriteLn ('Small number');
- 11..100 : WriteLn ('Normal, medium number');
- else
- WriteLn ('HUGE number');
- end;
- \end{verbatim}
- \subsection{The \var{If..then..else} statement}
- The \var{If .. then .. else..} prototype syntax is
- \input{syntax/ifthen.syn}
- The expression between the \var{if} and \var{then} keywords must have a
- boolean return type. If the expression evaluates to \var{True} then the
- statement following \var{then} is executed.
- If the expression evaluates to \var{False}, then the statement following
- \var{else} is executed, if it is present.
- Be aware of the fact that the boolean expression will be short-cut evaluated.
- (Meaning that the evaluation will be stopped at the point where the
- outcome is known with certainty)
- Also, before the \var {else} keyword, no semicolon (\var{;}) is allowed,
- but all statements can be compound statements.
- In nested \var{If.. then .. else} constructs, some ambiguity may araise as
- to which \var{else} statement pairs with which \var{if} statement. The rule
- is that the \var{else } keyword matches the first \var{if} keyword not
- already matched by an \var{else} keyword.
- For example:
- \begin{verbatim}
- If exp1 Then
- If exp2 then
- Stat1
- else
- stat2;
- \end{verbatim}
- Despite it's appearance, the statement is syntactically equivalent to
- \begin{verbatim}
- If exp1 Then
- begin
- If exp2 then
- Stat1
- else
- stat2
- end;
- \end{verbatim}
- and not to
- \begin{verbatim}
- { NOT EQUIVALENT }
- If exp1 Then
- begin
- If exp2 then
- Stat1
- end
- else
- stat2
- \end{verbatim}
- If it is this latter construct is needed, the \var{begin} and \var{end}
- keywords must be present. When in doubt, it is better to add them.
- The following is a valid statement:
- \begin{verbatim}
- If Today in [Monday..Friday] then
- WriteLn ('Must work harder')
- else
- WriteLn ('Take a day off.');
- \end{verbatim}
- \subsection{The \var{For..to/downto..do} statement}
- \fpc supports the \var{For} loop construction. A for loop is used in case
- one wants to calculated something a fixed number of times.
- The prototype syntax is as follows:
- \input{syntax/for.syn}
- \var{Statement} can be a compound statement.
- When this statement is encountered, the control variable is initialized with
- the initial value, and is compared with the final value.
- What happens next depends on whether \var{to} or \var{downto} is used:
- \begin{enumerate}
- \item In the case \var{To} is used, if the initial value is larger than the final
- value then \var{Statement} will never be executed.
- \item In the case \var{DownTo} is used, if the initial value is less than the final
- value then \var{Statement} will never be executed.
- \end{enumerate}
- After this check, the statement after \var{Do} is executed. After the
- execution of the statement, the control variable is increased or decreased
- with 1, depending on whether \var{To} or \var{Downto} is used.
- The control variable must be an ordinal type, no other
- types can be used as counters in a loop.
- \begin{remark}
- Contrary to ANSI pascal specifications, \fpc first initializes
- the counter variable, and only then calculates the upper bound.
- \end{remark}
- The following are valid loops:
- \begin{verbatim}
- For Day := Monday to Friday do Work;
- For I := 100 downto 1 do
- WriteLn ('Counting down : ',i);
- For I := 1 to 7*dwarfs do KissDwarf(i);
- \end{verbatim}
- If the statement is a compound statement, then the \seep{Break} and
- \seep{Continue} reserved words can be used to jump to the end or just
- after the end of the \var{For} statement.
- \subsection{The \var{Repeat..until} statement}
- The \var{repeat} statement is used to execute a statement until a certain
- condition is reached. The statement will be executed at least once.
- The prototype syntax of the \var{Repeat..until} statement is
- \input{syntax/repeat.syn}
- This will execute the statements between \var{repeat} and \var{until} up to
- the moment when \var{Expression} evaluates to \var{True}.
- Since the \var{expression} is evaluated {\em after} the execution of the
- statements, they are executed at least once.
- Be aware of the fact that the boolean expression \var{Expression} will be
- short-cut evaluated. (Meaning that the evaluation will be stopped at the
- point where the outcome is known with certainty)
- The following are valid \var{repeat} statements
- \begin{verbatim}
- repeat
- WriteLn ('I =',i);
- I := I+2;
- until I>100;
- repeat
- X := X/2
- until x<10e-3
- \end{verbatim}
- The \seep{Break} and \seep{Continue} reserved words can be used to jump to
- the end or just after the end of the \var{repeat .. until } statement.
- \subsection{The \var{While..do} statement}
- A \var{while} statement is used to execute a statement as long as a certain
- condition holds. This may imply that the statement is never executed.
- The prototype syntax of the \var{While..do} statement is
- \input{syntax/while.syn}
- This will execute \var{Statement} as long as \var{Expression} evaluates to
- \var{True}. Since \var{Expression} is evaluated {\em before} the execution
- of \var{Statement}, it is possible that \var{Statement} isn't executed at
- all. \var{Statement} can be a compound statement.
- Be aware of the fact that the boolean expression \var{Expression} will be
- short-cut evaluated. (Meaning that the evaluation will be stopped at the
- point where the outcome is known with certainty)
- The following are valid \var{while} statements:
- \begin{verbatim}
- I := I+2;
- while i<=100 do
- begin
- WriteLn ('I =',i);
- I := I+2;
- end;
- X := X/2;
- while x>=10e-3 do
- X := X/2;
- \end{verbatim}
- They correspond to the example loops for the \var{repeat} statements.
- If the statement is a compound statement, then the \seep{Break} and
- \seep{Continue} reserved words can be used to jump to the end or just
- after the end of the \var{While} statement.
- \subsection{The \var{With} statement}
- \label{se:With}
- The \var{with} statement serves to access the elements of a record
- or object or class, without having to specify the name of the each time.
- The syntax for a \var{with} statement is
- \input{syntax/with.syn}
- The variable reference must be a variable of a record, object or class type.
- In the \var{with} statement, any variable reference, or method reference is
- checked to see if it is a field or method of the record or object or class.
- If so, then that field is accessed, or that method is called.
- Given the declaration:
- \begin{verbatim}
- Type Passenger = Record
- Name : String[30];
- Flight : String[10];
- end;
- Var TheCustomer : Passenger;
- \end{verbatim}
- The following statements are completely equivalent:
- \begin{verbatim}
- TheCustomer.Name := 'Michael';
- TheCustomer.Flight := 'PS901';
- \end{verbatim}
- and
- \begin{verbatim}
- With TheCustomer do
- begin
- Name := 'Michael';
- Flight := 'PS901';
- end;
- \end{verbatim}
- The statement
- \begin{verbatim}
- With A,B,C,D do Statement;
- \end{verbatim}
- is equivalent to
- \begin{verbatim}
- With A do
- With B do
- With C do
- With D do Statement;
- \end{verbatim}
- This also is a clear example of the fact that the variables are tried {\em last
- to first}, i.e., when the compiler encounters a variable reference, it will
- first check if it is a field or method of the last variable. If not, then it
- will check the last-but-one, and so on.
- The following example shows this;
- \begin{verbatim}
- Program testw;
- Type AR = record
- X,Y : Longint;
- end;
- PAR = Record;
- Var S,T : Ar;
- begin
- S.X := 1;S.Y := 1;
- T.X := 2;T.Y := 2;
- With S,T do
- WriteLn (X,' ',Y);
- end.
- \end{verbatim}
- The output of this program is
- \begin{verbatim}
- 2 2
- \end{verbatim}
- Showing thus that the \var{X,Y} in the \var{WriteLn} statement match the
- \var{T} record variable.
- \begin{remark}
- When using a \var{With} statement with a pointer, or a class, it is not
- permitted to change the pointer or the class in the \var{With} block.
- With the definitions of the previous example, the following illustrates
- what it is about:
- \begin{verbatim}
- Var p : PAR;
- begin
- With P^ do
- begin
- // Do some operations
- P:=OtherP;
- X:=0.0; // Wrong X will be used !!
- end;
- \end{verbatim}
- The reason the pointer cannot be changed is that the address is stored
- by the compiler in a temporary register. Changing the pointer won't change
- the temporary address. The same is true for classes.
- \end{remark}
- \subsection{Exception Statements}
- \fpc supports exceptions. Exceptions provide a convenient way to
- program error and error-recovery mechanisms, and are
- closely related to classes.
- Exception support is explained in \seec{Exceptions}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Assembler statements
- \section{Assembler statements}
- An assembler statement allows to insert assembler code right in the
- pascal code.
- \input{syntax/statasm.syn}
- More information about assembler blocks can be found in the \progref.
- The register list is used to indicate the registers that are modified by an
- assembler statement in the assembler block. The compiler stores certain results in the
- registers. If the registers are modified in an assembler statement, the compiler
- should, sometimes, be told about it. The registers are denoted with their
- Intel names for the I386 processor, i.e., \var{'EAX'}, \var{'ESI'} etc...
- As an example, consider the following assembler code:
- \begin{verbatim}
- asm
- Movl $1,%ebx
- Movl $0,%eax
- addl %eax,%ebx
- end; ['EAX','EBX'];
- \end{verbatim}
- This will tell the compiler that it should save and restore the contents of
- the \var{EAX} and \var{EBX} registers when it encounters this asm statement.
- \fpc supports various styles of assembler syntax. By default, \var{AT\&T}
- syntax is assumed for the 80386 and compatibles platform.
- The default assembler style can be changed with the \var{\{\$asmmode xxx\}}
- switch in the code, or the \var{-R} command-line option. More about this can
- be found in the \progref.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Using functions and procedures.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Using functions and procedures}
- \label{ch:Procedures}
- \fpc supports the use of functions and procedures, but with some extras:
- Function overloading is supported, as well as \var{Const} parameters and
- open arrays.
- \begin{remark} In many of the subsequent paragraphs the words \var{procedure}
- and \var{function} will be used interchangeably. The statements made are
- valid for both, except when indicated otherwise.
- \end{remark}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Procedure declaration
- \section{Procedure declaration}
- A procedure declaration defines an identifier and associates it with a
- block of code. The procedure can then be called with a procedure statement.
- \input{syntax/procedur.syn}
- See \sees{Parameters} for the list of parameters.
- A procedure declaration that is followed by a block implements the action of
- the procedure in that block.
- The following is a valid procedure :
- \begin{verbatim}
- Procedure DoSomething (Para : String);
- begin
- Writeln ('Got parameter : ',Para);
- Writeln ('Parameter in upper case : ',Upper(Para));
- end;
- \end{verbatim}
- Note that it is possible that a procedure calls itself.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Function declaration
- \section{Function declaration}
- A function declaration defines an identifier and associates it with a
- block of code. The block of code will return a result.
- The function can then be called inside an expression, or with a procedure
- statement, if extended syntax is on.
- \input{syntax/function.syn}
- The result type of a function can be any previously declared type.
- contrary to Turbo pascal, where only simple types could be returned.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Parameter lists
- \section{Parameter lists}
- \label{se:Parameters}
- When arguments must be passed to a function or procedure, these parameters
- must be declared in the formal parameter list of that function or procedure.
- The parameter list is a declaration of identifiers that can be referred to
- only in that procedure or function's block.
- \input{syntax/params.syn}
- Constant parameters and variable parameters can also be \var{untyped}
- parameters if they have no type identifier.
- As of version 1.1, \fpc supports default values for both constant parameters
- and value parameters, but only for simple types. The compiler must be in
- \var{OBJFPC} or \var{DELPHI} mode to accept default values.
- \subsection{Value parameters}
- Value parameters are declared as follows:
- \input{syntax/paramval.syn}
- When parameters are declared as value parameters, the procedure gets {\em
- a copy} of the parameters that the calling block passes. Any modifications
- to these parameters are purely local to the procedure's block, and do not
- propagate back to the calling block.
- A block that wishes to call a procedure with value parameters must pass
- assignment compatible parameters to the procedure. This means that the types
- should not match exactly, but can be converted (conversion code is inserted
- by the compiler itself)
- Care must be taken when using value parameters: Value parameters makes heavy
- use of the stack, especially when using large parameters. The total size of
- all parameters in the formal parameter list should be below 32K for
- portability's sake (the Intel version limits this to 64K).
- Open arrays can be passed as value parameters. See \sees{openarray} for
- more information on using open arrays.
- For a parameter of a simple type (i.e. not a structured type), a default
- value can be specified. This can be an untyped constant. If the function
- call omits the parameter, the default value will be passed on to the
- function. For dynamic arrays or other types that can be considered as
- equivalent to a pointer, the only possible default value is \var{Nil}.
- The following example will print 20 on the screen:
- \begin{verbatim}
- program testp;
- Const
- MyConst = 20;
- Procedure MyRealFunc(I : Integer = MyConst);
- begin
- Writeln('Function received : ',I);
- end;
-
- begin
- MyRealFunc;
- end.
- \end{verbatim}
- \subsection{Variable parameters}
- \label{se:varparams}
- Variable parameters are declared as follows:
- \input{syntax/paramvar.syn}
- When parameters are declared as variable parameters, the procedure or
- function accesses immediatly the variable that the calling block passed in
- its parameter list. The procedure gets a pointer to the variable that was
- passed, and uses this pointer to access the variable's value.
- From this, it follows that any changes made to the parameter, will
- propagate back to the calling block. This mechanism can be used to pass
- values back in procedures.
- Because of this, the calling block must pass a parameter of {\em exactly}
- the same type as the declared parameter's type. If it does not, the compiler
- will generate an error.
- Variable and constant parameters can be untyped. In that case the variable has no type,
- and hence is incompatible with all other types. However, the address operator
- can be used on it, or it can be can passed to a function that has also an
- untyped parameter. If an untyped parameter is used in an assigment,
- or a value must be assigned to it, a typecast must be used.
- File type variables must always be passed as variable parameters.
- Open arrays can be passed as variable parameters. See \sees{openarray} for
- more information on using open arrays.
- Note that default values are not supported for variable parameters. This
- would make little sense since it defeats the purpose of being able to pass a
- value back to the caller.
- \subsection{Out parameters}
- \label{se:outparams}
- Out parameters (output parameters) are declared as follows:
- \input{syntax/paramout.syn}
- The purpose of an \var{out} parameter is to pass values back to the calling
- routine: The variable is passed by reference. The initial value of the
- parameter on function entry is discarded, and should not be used.
- If a variable must be used to pass a value to a function and retrieve data
- from the function, then a variable parameter must be used. If only a value
- must be retrieved, a \var{out} parameter can be used.
- Needless to say, default values are not supported for \var{out} parameters.
- \subsection{Constant parameters}
- In addition to variable parameters and value parameters \fpc also supports
- Constant parameters. A constant parameter as can be specified as follows:
- \input{syntax/paramcon.syn}
- A constant argument is passed by reference if it's size is larger than a
- pointer. It is passed by value if the size is equal or is less then the
- size of a native pointer.
- This means that the function or procedure receives a pointer to the passed
- argument, but it cannot be assigned to, this will result in a
- compiler error. Furthermore a const parameter cannot be passed on to another
- function that requires a variable parameter.
- The main use for this is reducing the stack size, hence improving
- performance, and still retaining the semantics of passing by value...
- Constant parameters can also be untyped. See \sees{varparams} for more
- information about untyped parameters.
- As for value parameters, constant parameters can get default values.
- Open arrays can be passed as constant parameters. See \sees{openarray} for
- more information on using open arrays.
- \subsection{Open array parameters}
- \label{se:openarray}
- \fpc supports the passing of open arrays, i.e. a procedure can be declared
- with an array of unspecified length as a parameter, as in Delphi.
- Open array parameters can be accessed in the procedure or function as an
- array that is declared with starting index 0, and last element
- index \var{High(paremeter)}.
- For example, the parameter
- \begin{verbatim}
- Row : Array of Integer;
- \end{verbatim}
- would be equivalent to
- \begin{verbatim}
- Row : Array[0..N-1] of Integer;
- \end{verbatim}
- Where \var{N} would be the actual size of the array that is passed to the
- function. \var{N-1} can be calculated as \var{High(Row)}.
- Open parameters can be passed by value, by reference or as a constant
- parameter. In the latter cases the procedure receives a pointer to the
- actual array. In the former case, it receives a copy of the array.
- In a function or procedure, open arrays can only be passed to functions which
- are also declared with open arrays as parameters, {\em not} to functions or
- procedures which accept arrays of fixed length.
- The following is an example of a function using an open array:
- \begin{verbatim}
- Function Average (Row : Array of integer) : Real;
- Var I : longint;
- Temp : Real;
- begin
- Temp := Row[0];
- For I := 1 to High(Row) do
- Temp := Temp + Row[i];
- Average := Temp / (High(Row)+1);
- end;
- \end{verbatim}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The array of const construct
- \subsection{Array of const}
- In Object Pascal or Delphi mode, \fpc supports the \var{Array of Const}
- construction to pass parameters to a subroutine.
- This is a special case of the \var{Open array} construction, where it is
- allowed to pass any expression in an array to a function or procedure.
- In the procedure, passed the arguments can be examined using a special
- record:
- \begin{verbatim}
- Type
- PVarRec = ^TVarRec;
- TVarRec = record
- case VType : Longint of
- vtInteger : (VInteger: Longint);
- vtBoolean : (VBoolean: Boolean);
- vtChar : (VChar: Char);
- vtExtended : (VExtended: PExtended);
- vtString : (VString: PShortString);
- vtPointer : (VPointer: Pointer);
- vtPChar : (VPChar: PChar);
- vtObject : (VObject: TObject);
- vtClass : (VClass: TClass);
- vtAnsiString : (VAnsiString: Pointer);
- vtWideString : (VWideString: Pointer);
- vtInt64 : (VInt64: PInt64);
- end;
- \end{verbatim}
- Inside the procedure body, the array of const is equivalent to
- an open array of TVarRec:
- \begin{verbatim}
- Procedure Testit (Args: Array of const);
- Var I : longint;
- begin
- If High(Args)<0 then
- begin
- Writeln ('No aguments');
- exit;
- end;
- Writeln ('Got ',High(Args)+1,' arguments :');
- For i:=0 to High(Args) do
- begin
- write ('Argument ',i,' has type ');
- case Args[i].vtype of
- vtinteger :
- Writeln ('Integer, Value :',args[i].vinteger);
- vtboolean :
- Writeln ('Boolean, Value :',args[i].vboolean);
- vtchar :
- Writeln ('Char, value : ',args[i].vchar);
- vtextended :
- Writeln ('Extended, value : ',args[i].VExtended^);
- vtString :
- Writeln ('ShortString, value :',args[i].VString^);
- vtPointer :
- Writeln ('Pointer, value : ',Longint(Args[i].VPointer));
- vtPChar :
- Writeln ('PCHar, value : ',Args[i].VPChar);
- vtObject :
- Writeln ('Object, name : ',Args[i].VObject.Classname);
- vtClass :
- Writeln ('Class reference, name :',Args[i].VClass.Classname);
- vtAnsiString :
- Writeln ('AnsiString, value :',AnsiString(Args[I].VAnsiStr
- else
- Writeln ('(Unknown) : ',args[i].vtype);
- end;
- end;
- end;
- \end{verbatim}
- In code, it is possible to pass an arbitrary array of elements
- to this procedure:
- \begin{verbatim}
- S:='Ansistring 1';
- T:='AnsiString 2';
- Testit ([]);
- Testit ([1,2]);
- Testit (['A','B']);
- Testit ([TRUE,FALSE,TRUE]);
- Testit (['String','Another string']);
- Testit ([S,T]) ;
- Testit ([P1,P2]);
- Testit ([@testit,Nil]);
- Testit ([ObjA,ObjB]);
- Testit ([1.234,1.234]);
- TestIt ([AClass]);
- \end{verbatim}
- If the procedure is declared with the \var{cdecl} modifier, then the
- compiler will pass the array as a C compiler would pass it. This, in effect,
- emulates the C construct of a variable number of arguments, as the following
- example will show:
- \begin{verbatim}
- program testaocc;
- {$mode objfpc}
- Const
- P : Pchar = 'example';
- Fmt : PChar =
- 'This %s uses printf to print numbers (%d) and strings.'#10;
- // Declaration of standard C function printf:
- procedure printf (fm : pchar; args : array of const);cdecl; external 'c';
- begin
- printf(Fmt,[P,123]);
- end.
- \end{verbatim}
- Remark that this is not true for Delphi, so code relying on this feature
- will not be portable.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Function overloading
- \section{Function overloading}
- Function overloading simply means that the same function is defined more
- than once, but each time with a different formal parameter list.
- The parameter lists must differ at least in one of it's elements type.
- When the compiler encounters a function call, it will look at the function
- parameters to decide which one of the defined functions it should call.
- This can be useful when the same function must be defined for different
- types. For example, in the RTL, the \var{Dec} procedure could be
- defined as:
- \begin{verbatim}
- ...
- Dec(Var I : Longint;decrement : Longint);
- Dec(Var I : Longint);
- Dec(Var I : Byte;decrement : Longint);
- Dec(Var I : Byte);
- ...
- \end{verbatim}
- When the compiler encounters a call to the dec function, it will first search
- which function it should use. It therefore checks the parameters in a
- function call, and looks if there is a function definition which matches the
- specified parameter list. If the compiler finds such a function, a call is
- inserted to that function. If no such function is found, a compiler error is
- generated.
- functions that have a \var{cdecl} modifier cannot be overloaded.
- (Technically, because this modifier prevents the mangling of
- the function name by the compiler).
- Prior to version 1.9 of the compiler, the overloaded functions needed to be
- in the same unit. Now the compiler will continue searching in other units if
- it doesn't find a matching version of an overloaded function in one unit.
- The compiler accepts the presence of the \var{overload} modifier as in
- Delphi, but it is not required, unless in Delphi mode.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % forward defined functions
- \section{Forward defined functions}
- A function can be declared without having it followed by it's implementation,
- by having it followed by the \var{forward} procedure. The effective
- implementation of that function must follow later in the module.
- The function can be used after a \var{forward} declaration as if it had been
- implemented already.
- The following is an example of a forward declaration.
- \begin{verbatim}
- Program testforward;
- Procedure First (n : longint); forward;
- Procedure Second;
- begin
- WriteLn ('In second. Calling first...');
- First (1);
- end;
- Procedure First (n : longint);
- begin
- WriteLn ('First received : ',n);
- end;
- begin
- Second;
- end.
- \end{verbatim}
- A function can be defined as forward only once.
- Likewise, in units, it is not allowed to have a forward declared function
- of a function that has been declared in the interface part. The interface
- declaration counts as a \var{forward} declaration.
- The following unit will give an error when compiled:
- \begin{verbatim}
- Unit testforward;
- interface
- Procedure First (n : longint);
- Procedure Second;
- implementation
- Procedure First (n : longint); forward;
- Procedure Second;
- begin
- WriteLn ('In second. Calling first...');
- First (1);
- end;
- Procedure First (n : longint);
- begin
- WriteLn ('First received : ',n);
- end;
- end.
- \end{verbatim}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % External functions
- \section{External functions}
- \label{se:external}
- The \var{external} modifier can be used to declare a function that resides in
- an external object file. It allows to use the function in some code, and at
- linking time, the object file containing the implementation of the function
- or procedure must be linked in.
- \input{syntax/external.syn}
- It replaces, in effect, the function or procedure code block.
- As an example:
- \begin{verbatim}
- program CmodDemo;
- {$Linklib c}
- Const P : PChar = 'This is fun !';
- Function strlen (P : PChar) : Longint; cdecl; external;
- begin
- WriteLn ('Length of (',p,') : ',strlen(p))
- end.
- \end{verbatim}
- \begin{remark}
- The parameters in our declaration of the \var{external} function
- should match exactly the ones in the declaration in the object file.
- \end{remark}
- If the \var{external} modifier is followed by a string constant:
- \begin{verbatim}
- external 'lname';
- \end{verbatim}
- Then this tells the compiler that the function resides in library
- 'lname'. The compiler will then automatically link this library to
- the program.
- The name that the function has in the library can also be specified:
- \begin{verbatim}
- external 'lname' name 'Fname';
- \end{verbatim}
- This tells the compiler that the function resides in library 'lname',
- but with name 'Fname'.The compiler will then automatically link this
- library to the program, and use the correct name for the function.
- Under \windows and \ostwo, the following form can also be used:
- \begin{verbatim}
- external 'lname' Index Ind;
- \end{verbatim}
- This tells the compiler that the function resides in library 'lname',
- but with index \var{Ind}. The compiler will then automatically
- link this library to the program, and use the correct index for the
- function.
- Finally, the external directive can be used to specify the external name
- of the function :
- \begin{verbatim}
- {$L myfunc.o}
- external name 'Fname';
- \end{verbatim}
- This tells the compiler that the function has the name 'Fname'. The
- correct library or object file (in this case myfunc.o) must still be linked.
- so that the function 'Fname' is included in the linking stage.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Assembler functions
- \section{Assembler functions}
- Functions and procedures can be completely implemented in assembly
- language. To indicate this, use the \var{assembler} keyword:
- \input{syntax/asm.syn}
- Contrary to Delphi, the assembler keyword must be present to indicate an
- assembler function.
- For more information about assembler functions, see the chapter on using
- assembler in the \progref.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Modifiers
- \section{Modifiers}
- A function or procedure declaration can contain modifiers. Here we list the
- various possibilities:
- \input{syntax/modifiers.syn}
- \fpc doesn't support all Turbo Pascal modifiers, but
- does support a number of additional modifiers. They are used mainly for assembler and
- reference to C object files.
- \subsection{alias}
- The \var{alias} modifier allows the programmer to specify a different name for a
- procedure or function. This is mostly useful for referring to this procedure
- from assembly language constructs or from another object file. As an example,
- consider the following program:
- \begin{verbatim}
- Program Aliases;
- Procedure Printit;alias : 'DOIT';
- begin
- WriteLn ('In Printit (alias : "DOIT")');
- end;
- begin
- asm
- call DOIT
- end;
- end.
- \end{verbatim}
- \begin{remark} the specified alias is inserted straight into the assembly
- code, thus it is case sensitive.
- \end{remark}
- The \var{alias} modifier does not make the symbol public to other modules,
- unless the routine is also declared in the interface part of a unit, or
- the \var{public} modifier is used to force it as public. Consider the
- following:
- \begin{verbatim}
- unit testalias;
- interface
- procedure testroutine;
- implementation
- procedure testroutine;alias:'ARoutine';
- begin
- WriteLn('Hello world');
- end;
- end.
- \end{verbatim}
- This will make the routine \var{testroutine} available publicly to
- external object files uunder the label name \var{ARoutine}.
- \subsection{cdecl}
- \label{se:cdecl}
- The \var{cdecl} modifier can be used to declare a function that uses a C
- type calling convention. This must be used when accessing functions residing in
- an object file generated by standard C compilers. It allows to use the function in
- the code, and at linking time, the object file containing the
- \var{C} implementation of the function or procedure must be linked in.
- As an example:
- \begin{verbatim}
- program CmodDemo;
- {$LINKLIB c}
- Const P : PChar = 'This is fun !';
- Function strlen (P : PChar) : Longint; cdecl; external name 'strlen';
- begin
- WriteLn ('Length of (',p,') : ',strlen(p))
- end.
- \end{verbatim}
- When compiling this, and linking to the C-library, the \var{strlen} function
- can be called throughout the program. The \var{external} directive tells
- the compiler that the function resides in an external object filebrary
- with the 'strlen' name (see \ref{se:external}).
- \begin{remark}
- The parameters in our declaration of the \var{C} function should
- match exactly the ones in the declaration in \var{C}.
- \end{remark}
- \subsection{export}
- The export modifier is used to export names when creating a shared library
- or an executable program. This means that the symbol will be publicly
- available, and can be imported from other programs. For more information
- on this modifier, consult the section on Programming dynamic libraries
- in the \progref.
- \subsection{inline}
- \label{se:inline}
- Procedures that are declared inline are copied to the places where they
- are called. This has the effect that there is no actual procedure call,
- the code of the procedure is just copied to where the procedure is needed,
- this results in faster execution speed if the function or procedure is
- used a lot.
- By default, \var{inline} procedures are not allowed. Inline code must be enabled
- using the command-line switch \var{-Si} or \var{\{\$inline on\}}
- directive.
- \begin{enumerate}
- \item Inline code is NOT exported from a unit. This means that when
- calling an inline procedure from another unit, a normal procedure call will be
- performed. Only inside units, \var{Inline} procedures are really inlined.
- \item Recursive inline functions are not allowed. i.e. an inline function
- that calls itself is not allowed.
- \end{enumerate}
- \subsection{interrupt}
- \label{se:interrupt}
- The \var{interrupt} keyword is used to declare a routine which will
- be used as an interrupt handler. On entry to this routine, all the registers
- will be saved and on exit, all registers will be restored
- and an interrupt or trap return will be executed (instead of the normal return
- from subroutine instruction).
- On platforms where a return from interrupt does not exist, the normal exit
- code of routines will be done instead. For more information on the generated
- code, consult the \progref.
- \subsection{pascal}
- \label{se:pascal}
- The \var{pascal} modifier can be used to declare a function that uses the
- classic pascal type calling convention (passing parameters from left to right).
- For more information on the pascal calling convention, consult the \progref.
- \subsection{popstack}
- \label{se:popstack}
- Popstack does the same as \var{cdecl}, namely it tells the \fpc compiler
- that a function uses the C calling convention. In difference with the
- \var{cdecl} modifier, it still mangles the name of the function as it would
- for a normal pascal function.
- With \var{popstack}, functions can be called by their pascal names in a
- library.
- \subsection{public}
- The \var{Public} keyword is used to declare a function globally in a unit.
- This is useful if the function should not be accessible from the unit
- file (i.e. another unit/program using the unit doesn't see the function),
- but must be accessible from the object file. as an example:
- \begin{verbatim}
- Unit someunit;
- interface
- Function First : Real;
- Implementation
- Function First : Real;
- begin
- First := 0;
- end;
- Function Second : Real; [Public];
- begin
- Second := 1;
- end;
- end.
- \end{verbatim}
- If another program or unit uses this unit, it will not be able to use the
- function \var{Second}, since it isn't declared in the interface part.
- However, it will be possible to access the function \var{Second} at the
- assembly-language level, by using it's mangled name (see the \progref).
- \subsection{register}
- \label{se:register}
- The \var{register} keyword is used for compatibility with Delphi. In
- version 1.0.x of the compiler, this directive has no effect on the
- generated code. As of the 1.9.X versions, this directive is supported. The
- first three arguments are passed in registers EAX,ECX and EDX.
- \subsection{saveregisters}
- If this modifier is specified after a procedure or function, then the
- \fpc compiler will save all registers on procedure entry, and restore
- them when the procedure exits (except for registers where return values
- are stored).
- This modifier is not used under normal circumstances, except maybe when
- calling assembler code.
- \subsection{safecall}
- This modifier ressembles closely the \var{stdcall} modifier. It sends
- parameters from right to left on the stack. The called procedure saves and
- restores all registers.
- More information about this modifier can be found in the \progref, in the
- section on the calling mechanism and the chapter on linking.
- \subsection{softfloat}
- This modifier makes sense only on the ARM architecture.
- \subsection{stdcall}
- This modifier pushes the parameters from right to left on the stack,
- it also aligns all the parameters to a default alignment.
- More information about this modifier can be found in the \progref, in the
- section on the calling mechanism and the chapter on linking.
- \subsection{varargs}
- This modifier can only be used together with the \var{cdecl} modifier, for
- external C procedures. It indicates that the procedure accepts a variable
- number of arguments after the last declared variable. These arguments are
- passed on without any type checking. It is equivalent to using the
- \var{array of const} construction for \var{cdecl} procedures, without having
- to declare the \var{array of const}. The square brackets around the variable
- arguments do not need to be used when this form of declaration is used.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Unsupported Turbo Pascal modifiers
- \section{Unsupported Turbo Pascal modifiers}
- The modifiers that exist in Turbo pascal, but aren't supported by \fpc, are
- listed in \seet{Modifs}.
- \begin{FPCltable}{lr}{Unsupported modifiers}{Modifs}
- Modifier & Why not supported ? \\ \hline
- Near & \fpc is a 32-bit compiler.\\
- Far & \fpc is a 32-bit compiler. \\
- \end{FPCltable}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Operator overloading
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Operator overloading}
- \label{ch:operatoroverloading}
- \section{Introduction}
- \fpc supports operator overloading. This means that it is possible to
- define the action of some operators on self-defined types, and thus allow
- the use of these types in mathematical expressions.
- Defining the action of an operator is much like the definition of a
- function or procedure, only there are some restrictions on the possible
- definitions, as will be shown in the subsequent.
- Operator overloading is, in essence, a powerful notational tool;
- but it is also not more than that, since the same results can be
- obtained with regular function calls. When using operator overloading,
- It is important to keep in mind that some implicit rules may produce
- some unexpected results. This will be indicated.
- \section{Operator declarations}
- To define the action of an operator is much like defining a function:
- \input{syntax/operator.syn}
- The parameter list for a comparision operator or an arithmetic operator
- must always contain 2 parameters. The result type of the comparision
- operator must be \var{Boolean}.
- \begin{remark}
- When compiling in \var{Delphi} mode or \var{Objfpc} mode, the result
- identifier may be dropped. The result can then be accessed through
- the standard \var{Result} symbol.
- If the result identifier is dropped and the compiler is not in one
- of these modes, a syntax error will occur.
- \end{remark}
- The statement block contains the necessary statements to determine the
- result of the operation. It can contain arbitrary large pieces of code;
- it is executed whenever the operation is encountered in some expression.
- The result of the statement block must always be defined; error conditions
- are not checked by the compiler, and the code must take care of all possible
- cases, throwing a run-time error if some error condition is encountered.
- In the following, the three types of operator definitions will be examined.
- As an example, throughout this chapter the following type will be used to
- define overloaded operators on :
- \begin{verbatim}
- type
- complex = record
- re : real;
- im : real;
- end;
- \end{verbatim}
- this type will be used in all examples.
- The sources of the Run-Time Library contain a unit \file{ucomplex},
- which contains a complete calculus for complex numbers, based on
- operator overloading.
- \section{Assignment operators}
- The assignment operator defines the action of a assignent of one type of
- variable to another. The result type must match the type of the variable
- at the left of the assignment statement, the single parameter to the
- assignment operator must have the same type as the expression at the
- right of the assignment operator.
- This system can be used to declare a new type, and define an assignment for
- that type. For instance, to be able to assign a newly defined type 'Complex'
- \begin{verbatim}
- Var
- C,Z : Complex; // New type complex
- begin
- Z:=C; // assignments between complex types.
- end;
- \end{verbatim}
- The following assignment operator would have to be defined:
- \begin{verbatim}
- Operator := (C : Complex) z : complex;
- \end{verbatim}
- To be able to assign a real type to a complex type as follows:
- \begin{verbatim}
- var
- R : real;
- C : complex;
- begin
- C:=R;
- end;
- \end{verbatim}
- the following assignment operator must be defined:
- \begin{verbatim}
- Operator := (r : real) z : complex;
- \end{verbatim}
- As can be seen from this statement, it defines the action of the operator
- \var{:=} with at the right a real expression, and at the left a complex
- expression.
- an example implementation of this could be as follows:
- \begin{verbatim}
- operator := (r : real) z : complex;
- begin
- z.re:=r;
- z.im:=0.0;
- end;
- \end{verbatim}
- As can be seen in the example, the result identifier (\var{z} in this case)
- is used to store the result of the assignment. When compiling in Delphi mode
- or objfpc mode, the use of the special identifier \var{Result} is also
- allowed, and can be substituted for the \var{z}, so the above would be
- equivalent to
- \begin{verbatim}
- operator := (r : real) z : complex;
- begin
- Result.re:=r;
- Result.im:=0.0;
- end;
- \end{verbatim}
- The assignment operator is also used to convert types from one type to
- another. The compiler will consider all overloaded assignment operators
- till it finds one that matches the types of the left hand and right hand
- expressions. If no such operator is found, a 'type mismatch' error
- is given.
- \begin{remark}
- The assignment operator is not commutative; the compiler will never reverse
- the role of the two arguments. in other words, given the above definition of
- the assignment operator, the following is {\em not} possible:
- \begin{verbatim}
- var
- R : real;
- C : complex;
- begin
- R:=C;
- end;
- \end{verbatim}
- if the reverse assignment should be possible (this is not so for reals and
- complex numbers) then the assigment operator must be defined for that as well.
- \end{remark}
- \begin{remark}
- The assignment operator is also used in implicit type conversions. This can
- have unwanted effects. Consider the following definitions:
- \begin{verbatim}
- operator := (r : real) z : complex;
- function exp(c : complex) : complex;
- \end{verbatim}
- then the following assignment will give a type mismatch:
- \begin{verbatim}
- Var
- r1,r2 : real;
- begin
- r1:=exp(r2);
- end;
- \end{verbatim}
- because the compiler will encounter the definition of the \var{exp} function
- with the complex argument. It implicitly converts r2 to a complex, so it can
- use the above \var{exp} function. The result of this function is a complex,
- which cannot be assigned to r1, so the compiler will give a 'type mismatch'
- error. The compiler will not look further for another \var{exp} which has
- the correct arguments.
- It is possible to avoid this particular problem by specifying
- \begin{verbatim}
- r1:=system.exp(r2);
- \end{verbatim}
- An experimental solution for this problem exists in the compiler, but is
- not enabled by default. Maybe someday it will be.
- \end{remark}
- \section{Arithmetic operators}
- Arithmetic operators define the action of a binary operator. Possible
- operations are:
- \begin{description}
- \item[multiplication] to multiply two types, the \var{*} multiplication
- operator must be overloaded.
- \item[division] to divide two types, the \var{/} division
- operator must be overloaded.
- \item[addition] to add two types, the \var{+} addition
- operator must be overloaded.
- \item[substraction] to substract two types, the \var{-} substraction
- operator must be overloaded.
- \item[exponentiation] to exponentiate two types, the \var{**} exponentiation
- operator must be overloaded.
- \end{description}
- The definition of an arithmetic operator takes two parameters. The first
- parameter must be of the type that occurs at the left of the operator,
- the second parameter must be of the type that is at the right of the
- arithmetic operator. The result type must match the type that results
- after the arithmetic operation.
- To compile an expression as
- \begin{verbatim}
- var
- R : real;
- C,Z : complex;
- begin
- C:=R*Z;
- end;
- \end{verbatim}
- one needs a definition of the multiplication operator as:
- \begin{verbatim}
- Operator * (r : real; z1 : complex) z : complex;
- begin
- z.re := z1.re * r;
- z.im := z1.im * r;
- end;
- \end{verbatim}
- As can be seen, the first operator is a real, and the second is
- a complex. The result type is complex.
- Multiplication and addition of reals and complexes are commutative
- operations. The compiler, however, has no notion of this fact so even
- if a multiplication between a real and a complex is defined, the
- compiler will not use that definition when it encounters a complex
- and a real (in that order). It is necessary to define both operations.
- So, given the above definition of the multiplication,
- the compiler will not accept the following statement:
- \begin{verbatim}
- var
- R : real;
- C,Z : complex;
- begin
- C:=Z*R;
- end;
- \end{verbatim}
- since the types of \var{Z} and \var{R} don't match the types in the
- operator definition.
- The reason for this behaviour is that it is possible that a multiplication
- is not always commutative. e.g. the multiplication of a \var{(n,m)} with a
- \var{(m,n)} matrix will result in a \var{(n,n)} matrix, while the
- mutiplication of a \var{(m,n)} with a \var{(n,m)} matrix is a \var{(m,m)}
- matrix, which needn't be the same in all cases.
- \section{Comparision operator}
- The comparision operator can be overloaded to compare two different types
- or to compare two equal types that are not basic types. The result type of
- a comparision operator is always a boolean.
- The comparision operators that can be overloaded are:
- \begin{description}
- \item[equal to] (=) to determine if two variables are equal.
- \item[less than] ($<$) to determine if one variable is less than another.
- \item[greater than] ($>$) to determine if one variable is greater than another.
- \item[greater than or equal to] ($>=$) to determine if one variable is greater than
- or equal to another.
- \item[less than or equal to] ($<=$) to determine if one variable is greater
- than or equal to another.
- \end{description}
- There is no separate operator for {\em unequal to} ($<>$). To evaluate a
- statement that contans the {\em unequal to} operator, the compiler uses the
- {\em equal to} operator (=), and negates the result.
- As an example, the following opetrator allows to compare two complex
- numbers:
- \begin{verbatim}
- operator = (z1, z2 : complex) b : boolean;
- \end{verbatim}
- the above definition allows comparisions of the following form:
- \begin{verbatim}
- Var
- C1,C2 : Complex;
- begin
- If C1=C2 then
- Writeln('C1 and C2 are equal');
- end;
- \end{verbatim}
- The comparision operator definition needs 2 parameters, with the types that
- the operator is meant to compare. Here also, the compiler doesn't apply
- commutativity; if the two types are different, then it necessary to
- define 2 comparision operators.
- In the case of complex numbers, it is, for instance necessary to define
- 2 comparsions: one with the complex type first, and one with the real type
- first.
- Given the definitions
- \begin{verbatim}
- operator = (z1 : complex;r : real) b : boolean;
- operator = (r : real; z1 : complex) b : boolean;
- \end{verbatim}
- the following two comparisions are possible:
- \begin{verbatim}
- Var
- R,S : Real;
- C : Complex;
- begin
- If (C=R) or (S=C) then
- Writeln ('Ok');
- end;
- \end{verbatim}
- Note that the order of the real and complex type in the two comparisions
- is reversed.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Programs, Units, Blocks
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Programs, units, blocks}
- A Pascal program consists of modules called \var{units}. A unit can be used
- to group pieces of code together, or to give someone code without giving
- the sources.
- Both programs and units consist of code blocks, which are mixtures of
- statements, procedures, and variable or type declarations.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Programs
- \section{Programs}
- A pascal program consists of the program header, followed possibly by a
- 'uses' clause, and a block.
- \input{syntax/program.syn}
- The program header is provided for backwards compatibility, and is ignored
- by the compiler.
- The uses clause serves to identify all units that are needed by the program.
- The system unit doesn't have to be in this list, since it is always loaded
- by the compiler.
- The order in which the units appear is significant, it determines in
- which order they are initialized. Units are initialized in the same order
- as they appear in the uses clause. Identifiers are searched in the opposite
- order, i.e. when the compiler searches for an identifier, then it looks
- first in the last unit in the uses clause, then the last but one, and so on.
- This is important in case two units declare different types with the same
- identifier.
- When the compiler looks for unit files, it adds the extension \file{.ppu}
- (\file{.ppw} for Win32 platforms) to the name of the unit. On \linux and in
- operating systems where filenames are case sensitive, when looking for a unit,
- the unit name is first looked for in the original case, and when not found,
- converted to all lowercase and searched for.
- If a unit name is longer than 8 characters, the compiler will first look for
- a unit name with this length, and then it will truncate the name to 8
- characters and look for it again. For compatibility reasons, this is also
- true on platforms that suport long file names.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Units
- \section{Units}
- A unit contains a set of declarations, procedures and functions that can be
- used by a program or another unit.
- The syntax for a unit is as follows:
- \input{syntax/unit.syn}
- The interface part declares all identifiers that must be exported from the
- unit. This can be constant, type or variable identifiers, and also procedure
- or function identifier declarations. Declarations inside the
- implementation part are {\em not} accessible outside the unit. The
- implementation must contain a function declaration for each function or
- procedure that is declared in the interface part. If a function is declared
- in the interface part, but no declaration of that function is present in the
- implementation part, then the compiler will give an error.
- When a program uses a unit (say \file{unitA}) and this units uses a second
- unit, say \file{unitB}, then the program depends indirectly also on
- \var{unitB}. This means that the compiler must have access to \file{unitB} when
- trying to compile the program. If the unit is not present at compile time,
- an error occurs.
- Note that the identifiers from a unit on which a program depends indirectly,
- are not accessible to the program. To have access to the identifiers of a
- unit, the unit must be in the uses clause of the program or unit where the
- identifiers are needed.
- Units can be mutually dependent, that is, they can reference each other in
- their uses clauses. This is allowed, on the condition that at least one of
- the references is in the implementation section of the unit. This also holds
- for indirect mutually dependent units.
- If it is possible to start from one interface uses clause of a unit, and to return
- there via uses clauses of interfaces only, then there is circular unit
- dependence, and the compiler will generate an error.
- As and example : the following is not allowed:
- \begin{verbatim}
- Unit UnitA;
- interface
- Uses UnitB;
- implementation
- end.
- Unit UnitB
- interface
- Uses UnitA;
- implementation
- end.
- \end{verbatim}
- But this is allowed :
- \begin{verbatim}
- Unit UnitA;
- interface
- Uses UnitB;
- implementation
- end.
- Unit UnitB
- implementation
- Uses UnitA;
- end.
- \end{verbatim}
- Because \file{UnitB} uses \file{UnitA} only in it's implentation section.
- In general, it is a bad idea to have circular unit dependencies, even if it is
- only in implementation sections.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Blocks
- \section{Blocks}
- Units and programs are made of blocks. A block is made of declarations of
- labels, constants, types variables and functions or procedures. Blocks can
- be nested in certain ways, i.e., a procedure or function declaration can
- have blocks in themselves.
- A block looks like the following:
- \input{syntax/block.syn}
- Labels that can be used to identify statements in a block are declared in
- the label declaration part of that block. Each label can only identify one
- statement.
- Constants that are to be used only in one block should be declared in that
- block's constant declaration part.
- Variables that are to be used only in one block should be declared in that
- block's constant declaration part.
- Types that are to be used only in one block should be declared in that
- block's constant declaration part.
- Lastly, functions and procedures that will be used in that block can be
- declared in the procedure/function declaration part.
- After the different declaration parts comes the statement part. This
- contains any actions that the block should execute.
- All identifiers declared before the statement part can be used in that
- statement part.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Scope
- \section{Scope}
- Identifiers are valid from the point of their declaration until the end of
- the block in which the declaration occurred. The range where the identifier
- is known is the {\em scope} of the identifier. The exact scope of an
- identifier depends on the way it was defined.
- \subsection{Block scope}
- The {\em scope} of a variable declared in the declaration part of a block,
- is valid from the point of declaration until the end of the block.
- If a block contains a second block, in which the identfier is
- redeclared, then inside this block, the second declaration will be valid.
- Upon leaving the inner block, the first declaration is valid again.
- Consider the following example:
- \begin{verbatim}
- Program Demo;
- Var X : Real;
- { X is real variable }
- Procedure NewDeclaration
- Var X : Integer; { Redeclare X as integer}
- begin
- // X := 1.234; {would give an error when trying to compile}
- X := 10; { Correct assigment}
- end;
- { From here on, X is Real again}
- begin
- X := 2.468;
- end.
- \end{verbatim}
- In this example, inside the procedure, X denotes an integer variable.
- It has it's own storage space, independent of the variable \var{X} outside
- the procedure.
- \subsection{Record scope}
- The field identifiers inside a record definition are valid in the following
- places:
- \begin{enumerate}
- \item to the end of the record definition.
- \item field designators of a variable of the given record type.
- \item identifiers inside a \var{With} statement that operates on a variable
- of the given record type.
- \end{enumerate}
- \subsection{Class scope}
- A component identifier is valid in the following places:
- \begin{enumerate}
- \item From the point of declaration to the end of the class definition.
- \item In all descendent types of this class, unless it is in the private
- part of the class declaration.
- \item In all method declaration blocks of this class and descendent classes.
- \item In a with statement that operators on a variable of the given class's
- definition.
- \end{enumerate}
- Note that method designators are also considered identifiers.
- \subsection{Unit scope}
- All identifiers in the interface part of a unit are valid from the point of
- declaration, until the end of the unit. Furthermore, the identifiers are
- known in programs or units that have the unit in their uses clause.
- Identifiers from indirectly dependent units are {\em not} available.
- Identifiers declared in the implementation part of a unit are valid from the
- point of declaration to the end of the unit.
- The system unit is automatically used in all units and programs.
- It's identifiers are therefore always known, in each pascal program, library
- or unit.
- The rules of unit scope imply that an identifier of a
- unit can be redefined. To have access to an identifier of another unit that was redeclared in
- the current unit, precede it with that other units name, as in the following
- example:
- \begin{verbatim}
- unit unitA;
- interface
- Type
- MyType = Real;
- implementation
- end.
- Program prog;
- Uses UnitA;
- { Redeclaration of MyType}
- Type MyType = Integer;
- Var A : Mytype; { Will be Integer }
- B : UnitA.MyType { Will be real }
- begin
- end.
- \end{verbatim}
- This is especially useful when redeclaring the system unit's identifiers.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Libraries
- \section{Libraries}
- \fpc supports making of dynamic libraries (DLLs under Win32 and \ostwo) trough
- the use of the \var{Library} keyword.
- A Library is just like a unit or a program:
- \input{syntax/library.syn}
- By default, functions and procedures that are declared and implemented in
- library are not available to a programmer that wishes to use this library.
- In order to make functions or procedures available from the library,
- they must be exported in an export clause:
- \input{syntax/exports.syn}
- Under Win32, an index clause can be added to an exports entry.
- an index entry must be a positive number larger or equal than 1.
- Optionally, an exports entry can have a name specifier. If present, the name
- specifier gives the exact name (case sensitive) of the function in the
- library.
- If neither of these constructs is present, the functions or procedures
- are exported with the exact names as specified in the exports clause.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Exceptions
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Exceptions}
- \label{ch:Exceptions}
- Exceptions provide a convenient way to program error and error-recovery
- mechanisms, and are closely related to classes.
- Exception support is based on 3 constructs:
- \begin{description}
- \item [Raise\ ] statements. To raise an exeption. This is usually done to signal an
- error condition.
- \item [Try ... Except\ ] blocks. These block serve to catch exceptions
- raised within the scope of the block, and to provide exception-recovery
- code.
- \item [Try ... Finally\ ] blocks. These block serve to force code to be
- executed irrespective of an exception occurrence or not. They generally
- serve to clean up memory or close files in case an exception occurs.
- The compiler generates many implicit \var{Try ... Finally} blocks around
- procedure, to force memory consistence.
- \end{description}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The raise statement
- \section{The raise statement}
- The \var{raise} statement is as follows:
- \input{syntax/raise.syn}
- This statement will raise an exception. If it is specified, the exception
- instance must be an initialized instance of a class, which is the raise
- type. The address exception is optional. If itis not specified, the compiler
- will provide the address by itself.
- If the exception instance is omitted, then the current exception is
- re-raised. This construct can only be used in an exception handling
- block (see further).
- \begin{remark} Control {\em never} returns after an exception block. The
- control is transferred to the first \var{try...finally} or
- \var{try...except} statement that is encountered when unwinding the stack.
- If no such statement is found, the \fpc Run-Time Library will generate a
- run-time error 217 (see also \sees{exceptclasses}).
- \end{remark}
- As an example: The following division checks whether the denominator is
- zero, and if so, raises an exception of type \var{EDivException}
- \begin{verbatim}
- Type EDivException = Class(Exception);
- Function DoDiv (X,Y : Longint) : Integer;
- begin
- If Y=0 then
- Raise EDivException.Create ('Division by Zero would occur');
- Result := X Div Y;
- end;
- \end{verbatim}
- The class \var{Exception} is defined in the \file{Sysutils} unit of the rtl.
- (\sees{exceptclasses})
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The try...except statement
- \section{The try...except statement}
- A \var{try...except} exception handling block is of the following form :
- \input{syntax/try.syn}
- If no exception is raised during the execution of the \var{statement list},
- then all statements in the list will be executed sequentially, and the
- except block will be skipped, transferring program flow to the statement
- after the final \var{end}.
- If an exception occurs during the execution of the \var{statement list}, the
- program flow will be transferred to the except block. Statements in the
- statement list between the place where the exception was raised and the
- exception block are ignored.
- In the exception handling block, the type of the exception is checked,
- and if there is an exception handler where the class type matches the
- exception object type, or is a parent type of
- the exception object type, then the statement following the corresponding
- \var{Do} will be executed. The first matching type is used. After the
- \var{Do} block was executed, the program continues after the \var{End}
- statement.
- The identifier in an exception handling statement is optional, and declares
- an exception object. It can be used to manipulate the exception object in
- the exception handling code. The scope of this declaration is the statement
- block foillowing the \var{Do} keyword.
- If none of the \var{On} handlers matches the exception object type, then the
- statement list after \var{else} is executed. If no such list is
- found, then the exception is automatically re-raised. This process allows
- to nest \var{try...except} blocks.
- If, on the other hand, the exception was caught, then the exception object is
- destroyed at the end of the exception handling block, before program flow
- continues. The exception is destroyed through a call to the object's
- \var{Destroy} destructor.
- As an example, given the previous declaration of the \var{DoDiv} function,
- consider the following
- \begin{verbatim}
- Try
- Z := DoDiv (X,Y);
- Except
- On EDivException do Z := 0;
- end;
- \end{verbatim}
- If \var{Y} happens to be zero, then the DoDiv function code will raise an
- exception. When this happens, program flow is transferred to the except
- statement, where the Exception handler will set the value of \var{Z} to
- zero. If no exception is raised, then program flow continues past the last
- \var{end} statement.
- To allow error recovery, the \var{Try ... Finally} block is supported.
- A \var{Try...Finally} block ensures that the statements following the
- \var{Finally} keyword are guaranteed to be executed, even if an exception
- occurs.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % The try...finally statement
- \section{The try...finally statement}
- A \var{Try..Finally} statement has the following form:
- \input{syntax/finally.syn}
- If no exception occurs inside the \var{statement List}, then the program
- runs as if the \var{Try}, \var{Finally} and \var{End} keywords were not
- present.
- If, however, an exception occurs, the program flow is immediatly
- transferred from the point where the excepion was raised to the first
- statement of the \var{Finally statements}.
- All statements after the finally keyword will be executed, and then
- the exception will be automatically re-raised. Any statements between the
- place where the exception was raised and the first statement of the
- \var{Finally Statements} are skipped.
- As an example consider the following routine:
- \begin{verbatim}
- Procedure Doit (Name : string);
- Var F : Text;
- begin
- Try
- Assign (F,Name);
- Rewrite (name);
- ... File handling ...
- Finally
- Close(F);
- end;
- \end{verbatim}
- If during the execution of the file handling an execption occurs, then
- program flow will continue at the \var{close(F)} statement, skipping any
- file operations that might follow between the place where the exception
- was raised, and the \var{Close} statement.
- If no exception occurred, all file operations will be executed, and the file
- will be closed at the end.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Exception handling nesting
- \section{Exception handling nesting}
- It is possible to nest \var{Try...Except} blocks with \var{Try...Finally}
- blocks. Program flow will be done according to a \var{lifo} (last in, first
- out) principle: The code of the last encountered \var{Try...Except} or
- \var{Try...Finally} block will be executed first. If the exception is not
- caught, or it was a finally statement, program flow will be transferred to
- the last-but-one block, {\em ad infinitum}.
- If an exception occurs, and there is no exception handler present, then a
- runerror 217 will be generated. When using the \file{sysutils} unit, a default
- handler is installed which will show the exception object message, and the
- address where the exception occurred, after which the program will exit with
- a \var{Halt} instruction.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Exception classes
- \section{Exception classes}
- \label{se:exceptclasses}
- The \file{sysutils} unit contains a great deal of exception handling.
- It defines the following exception types:
- \begin{verbatim}
- Exception = class(TObject)
- private
- fmessage : string;
- fhelpcontext : longint;
- public
- constructor create(const msg : string);
- constructor createres(indent : longint);
- property helpcontext : longint read fhelpcontext write fhelpcontext;
- property message : string read fmessage write fmessage;
- end;
- ExceptClass = Class of Exception;
- { mathematical exceptions }
- EIntError = class(Exception);
- EDivByZero = class(EIntError);
- ERangeError = class(EIntError);
- EIntOverflow = class(EIntError);
- EMathError = class(Exception);
- \end{verbatim}
- The sysutils unit also installs an exception handler. If an exception is
- unhandled by any exception handling block, this handler is called by the
- Run-Time library. Basically, it prints the exception address, and it prints
- the message of the Exception object, and exits with a exit code of 217.
- If the exception object is not a descendent object of the \var{Exception}
- object, then the class name is printed instead of the exception message.
- It is recommended to use the \var{Exception} object or a descendant class for
- all \var{raise} statements, since then the message field of the
- exception object can be used.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Using Assembler
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \chapter{Using assembler}
- \fpc supports the use of assembler in code, but not inline
- assembler macros. To have more information on the processor
- specific assembler syntax and its limitations, see the \progref.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Assembler statements
- \section{Assembler statements }
- The following is an example of assembler inclusion in pascal code.
- \begin{verbatim}
- ...
- Statements;
- ...
- Asm
- the asm code here
- ...
- end;
- ...
- Statements;
- \end{verbatim}
- The assembler instructions between the \var{Asm} and \var{end} keywords will
- be inserted in the assembler generated by the compiler.
- Conditionals can be used ib assembler, the compiler will recognise it,
- and treat it as any other conditionals.
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Assembler procedures and functions
- \section{Assembler procedures and functions}
- Assembler procedures and functions are declared using the
- \var{Assembler} directive. This permits the code generator to make a number
- of code generation optimizations.
- The code generator does not generate any stack frame (entry and exit
- code for the routine) if it contains no local variables and no
- parameters. In the case of functions, ordinal values must be returned
- in the accumulator. In the case of floating point values, these depend
- on the target processor and emulation options.
- %
- % The index.
- %
- \printindex
- \end{document}
|