RATFOR—APreprocessorforaRationalFortran BrianW.Kernighan structuredprogramming,controlflow,programming ABSTRACT AlthoughFortranisnotapleasantlanguagetouse,itdoeshavetheadvantagesof universalityand(usually)relativeefficiency.TheRatforlanguageattemptstoconcealthe maindeficienciesofFortranwhileretainingitsdesirablequalities,byprovidingdecentcontrolflowstatements: •statementgrouping •if-elseandswitchfordecision-making •while,for,do,andrepeat-untilforlooping •breakandnextforcontrollingloopexits andsome‘‘syntacticsugar’’: •freeforminput(multiplestatements/line,automaticcontinuation) •unobtrusivecommentconvention •translationof>,>=,etc.,into.GT.,.GE.,etc. •return(expression)statementforfunctions •definestatementforsymbolicparameters •includestatementforincludingsourcefiles RatforisimplementedasapreprocessorwhichtranslatesthislanguageintoFortran. OncethecontrolflowandcosmeticdeficienciesofFortranarehidden,theresulting languageisremarkablypleasanttouse.Ratforprogramsaremarkedlyeasiertowrite,and toread,andthuseasiertodebug,maintainandmodifythantheirFortranequivalents. ItisreadilypossibletowriteRatforprogramswhichareportabletootherenvironments.Ratforiswritteninitselfinthisway,soitisalsoportable;versionsofRatforare nowrunningonatleasttwodozendifferenttypesofcomputersatoverfivehundredlocations. ThispaperdiscussesdesigncriteriaforaFortranpreprocessor,theRatforlanguage anditsimplementation,anduserexperience. 9April1993 RATFOR—APreprocessorforaRationalFortran BrianW.Kernighan structuredprogramming,controlflow,programming 1.INTRODUCTION MostprogrammerswillagreethatFortranis anunpleasantlanguagetoprogramin,yetthere aremanyoccasionswhentheyareforcedtouseit. Forexample,Fortranisoftentheonlylanguage thoroughlysupportedonthelocalcomputer. Indeed,itistheclosestthingtoauniversalprogramminglanguagecurrentlyavailable:withcare itispossibletowritelarge,trulyportableFortran programs[1].Finally,Fortranisoftenthemost ‘‘efficient’’languageavailable,particularlyforprogramsrequiringmuchcomputation. ButFortranisunpleasant.Perhapsthe worstdeficiencyisinthecontrolflowstatements —conditionalbranchesandloops—which expressthelogicoftheprogram.Theconditional statementsinFortranareprimitive.TheArithmeticIFforcestheuserintoatleasttwostatement numbersandtwo(implied)GOTO’s;itleadsto unintelligiblecode,andiseschewedbygoodprogrammers.TheLogicalIFisbetter,inthatthe testpartcanbestatedclearly,buthopelessly restrictivebecausethestatementthatfollowsthe IFcanonlybeoneFortranstatement(withsome furtherrestrictions!).Andofcoursetherecanbe noELSEparttoaFortranIF:thereisnowayto specifyanalternativeactioniftheIFisnotsatisfied. TheFortranDOrestrictstheusertogoing forwardinanarithmeticprogression.Itisfinefor ‘‘1toNinstepsof1(or2or...)’’,butthereisno directwaytogobackwards,oreven(inANSIFortran[2])togofrom1toN−1.Andofcoursethe DOisuselessifone’sproblemdoesn’tmapintoan arithmeticprogression. TheresultofthesefailingsisthatFortran programsmustbewrittenwithnumerouslabels andbranches.Theresultingcodeisparticularly difficulttoreadandunderstand,andthushardto debugandmodify. Whenoneisfacedwithanunpleasantlanguage,ausefultechniqueistodefineanewlanguagethatovercomesthedeficiencies,andto translateitintotheunpleasantonewithapreprocessor.ThisistheapproachtakenwithRatfor. ThispaperisarevisedandexpandedversionofoepublishedinSoftware—PracticeandExperience, October1975.TheRatfordescribedhereistheoneinuseonUNIXandGCOSatBellLaboratories, MurrayHill,N.J.

(Thepreprocessorideaisofcoursenotnew,and preprocessorsforFortranareespeciallypopular today.Arecentlisting[3]ofpreprocessorsshows morethan50,ofwhichatleasthalfadozenare widelyavailable.) 2.LANGUAGEDESCRIPTION Design RatforattemptstoretainthemeritsofFortran(universality,portability,efficiency)whilehidingtheworstFortraninadequacies.Thelanguage isFortranexceptfortwoaspects.First,sincecontrolflowiscentraltoanyprogram,regardlessof thespecificapplication,theprimarytaskofRatfor istoconcealthispartofFortranfromtheuser,by providingdecentcontrolflowstructures.These structuresaresufficientandcomfortableforstructuredprogramminginthenarrowsenseofprogrammingwithoutGOTO’s.Second,sincethepreprocessormustexamineanentireprogramto translatethecontrolstructure,itispossibleatthe sametimetocleanupmanyofthe‘‘cosmetic’’deficienciesofFortran,andthusprovidealanguage whichiseasierandmorepleasanttoreadand write. Beyondthesetwoaspects—controlflow andcosmetics—Ratfordoesnothingaboutthe hostofotherweaknessesofFortran.Althoughit wouldbestraightforwardtoextendittoprovide characterstrings,forexample,theyarenotneeded byeveryone,andofcoursethepreprocessorwould behardertoimplement.Throughout,thedesign principlewhichhasdeterminedwhatshouldbein RatforandwhatshouldnothasbeenRatfor doesn’tknowanyFortran.Anylanguagefeature whichwouldrequirethatRatforreallyunderstand Fortranhasbeenomitted.Wewillreturntothis pointinthesectiononimplementation. Evenwithintheconfinesofcontrolflowand cosmetics,wehaveattemptedtobeselectivein whatfeaturestoprovide.Theintenthasbeento provideasmallsetofthemostusefulconstructs, ratherthantothrowineverythingthathasever beenthoughtusefulbysomeone.

-2-Therestofthissectioncontainsaninformal descriptionoftheRatforlanguage.Thecontrol flowaspectswillbequitefamiliartoreadersused tolanguageslikeAlgol,PL/I,Pascal,etc.,andthe cosmeticchangesareequallystraightforward.We shallconcentrateonshowingwhatthelanguage lookslike. StatementGrouping Fortranprovidesnowaytogroupstatementstogether,shortofmakingthemintoasubroutine.Thestandardconstruction‘‘ifacondition istrue,dothisgroupofthings,’’forexample, if(x>100) {callerror("x>100");err=1;return} cannotbewrittendirectlyinFortran.Insteada programmerisforcedtotranslatethisrelatively clearthoughtintomurkyFortran,bystatingthe negativeconditionandbranchingaroundthe groupofstatements: if(x.le.100)goto10 callerror(5hx>100) err=1 return 10... Whentheprogramdoesn’twork,orwhenitmust bemodified,thismustbetranslatedbackintoa clearerformbeforeonecanbesurewhatitdoes. Ratforeliminatesthiserror-proneandcon-fusingback-and-forthtranslation;thefirstformis thewaythecomputationiswritteninRatfor.A groupofstatementscanbetreatedasaunitby enclosingtheminthebraces{and}.Thisistrue throughoutthelanguage:whereverasingleRatfor statementcanbeused,therecanbeseveral enclosedinbraces.(Bracesseemclearerandless obtrusivethanbeginandendordoandend, andofcoursedoandendalreadyhaveFortran meanings.) Cosmeticscontributetothereadabilityof code,andthustoitsunderstandability.Thecharacter‘‘>’’isclearerthan‘‘.GT.’’,soRatfortranslatesitappropriately,alongwithseveralothersimilarshorthands.AlthoughmanyFortrancompilers permitcharacterstringsinquotes(like"x>100"), quotesarenotallowedinANSIFortran,soRatfor convertsitintotherightnumberofH’s:computerscountbetterthanpeopledo. Ratforisafree-formlanguage:statements mayappearanywhereonaline,andseveralmay appearononelineiftheyareseparatedbysemicolons.Theexampleabovecouldalsobewritten as if(x>100){ callerror("x>100") err=1 return } Inthiscase,nosemicolonisneededattheendof eachlinebecauseRatforassumesthereisone statementperlineunlesstoldotherwise. Ofcourse,ifthestatementthatfollowsthe ifisasinglestatement(Ratfororotherwise),no bracesareneeded: if(y<=0.0&z<=0.0) write(6,20)y,z Nocontinuationneedbeindicatedbecausethe statementisclearlynotfinishedonthefirstline. IngeneralRatforcontinueslineswhenitseems obviousthattheyarenotyetdone.(Thecontinuationconventionisdiscussedindetaillater.) Althoughafree-formlanguagepermitswide latitudeinformattingstyles,itiswisetopickone thatisreadable,thensticktoit.Inparticular, properindentationisvital,tomakethelogical structureoftheprogramobvioustothereader. The‘‘else’’Clause Ratforprovidesanelsestatementtohandle theconstruction‘‘ifaconditionistrue,dothis thing,otherwisedothatthing.’’ if(a<=b) {sw=0;write(6,1)a,b} else {sw=1;write(6,1)b,a} Thiswritesoutthesmallerofaandb,thenthe larger,andsetsswappropriately. TheFortranequivalentofthiscodeiscircuitousindeed: if(a.gt.b)goto10 sw=0 write(6,1)a,b goto20 10sw=1 write(6,1)b,a 20... Thisisamechanicaltranslation;shorterforms exist,astheydoformanysimilarsituations.But alltranslationssufferfromthesameproblem:since theyaretranslations,theyarelessclearand understandablethancodethatisnotatranslation. TounderstandtheFortranversion,onemustscan theentireprogramtomakesurethatnoother statementbranchestostatements10or20before oneknowsthatindeedthisisanif-elseconstruc-tion.WiththeRatforversion,thereisnoquestion -3-abouthowonegetstothepartsofthestatement. Theif-elseisasingleunit,whichcanberead, understood,andignoredifnotrelevant.Theprogramsayswhatitmeans. Asbefore,ifthestatementfollowinganifor anelseisasinglestatement,nobracesare needed: if(a<=b) sw=0 else sw=1 Thesyntaxoftheifstatementis if(legalFortrancondition) Ratforstatement else Ratforstatement wheretheelsepartisoptional.ThelegalFortran conditionisanythingthatcanlegallygointoa FortranLogicalIF.Ratfordoesnotcheckthis clause,sinceitdoesnotknowenoughFortranto knowwhatispermitted.TheRatforstatementis anyRatfororFortranstatement,oranycollection oftheminbraces. Nestedif’s Sincethestatementthatfollowsaniforan elsecanbeanyRatforstatement,thisleads immediatelytothepossibilityofanotherifor else.Asausefulexample,considerthisproblem: thevariablefistobesetto−1ifxislessthan zero,to+1ifxisgreaterthan100,andto0otherwise.TheninRatfor,wewrite if(x<0) f=−1 elseif(x>100) f=+1 else f=0 Herethestatementafterthefirstelseisanother if-else.Logicallyitisjustasinglestatement, althoughitisrathercomplicated. Thiscodesayswhatitmeans.Anyversion writteninstraightFortranwillnecessarilybeindirectbecauseFortrandoesnotletyousaywhatyou mean.Andasalways,clevershortcutsmayturn outtobetooclevertounderstandayearfrom now. Followinganelsewithanifisonewayto writeamulti-waybranchinRatfor.Ingeneralthe structure if(...) −−− elseif(...) −−− elseif(...) −−− ... else −−− providesawaytospecifythechoiceofexactlyone ofseveralalternatives.(Ratforalsoprovidesa switchstatementwhichdoesthesamejobincertainspecialcases;inmoregeneralsituations,we havetomakedowithspareparts.)Thetestsare laidoutinsequence,andeachoneisfollowedby thecodeassociatedwithit.Readdownthelistof decisionsuntiloneisfoundthatissatisfied.The codeassociatedwiththisconditionisexecuted, andthentheentirestructureisfinished.The trailingelseparthandlesthe‘‘default’’case,where noneoftheotherconditionsapply.Ifthereisno defaultaction,thisfinalelsepartisomitted: if(x<0) x=0 elseif(x>100) x=100 if-elseambiguity Thereisonethingtonoticeaboutcomplicatedstructuresinvolvingnestedif’sandelse’s. Consider if(x>0) if(y>0) write(6,1)x,y else write(6,2)y Therearetwoif’sandonlyoneelse.Whichif doestheelsegowith? ThisisagenuineambiguityinRatfor,asit isinmanyotherprogramminglanguages.The ambiguityisresolvedinRatfor(aselsewhere)by sayingthatinsuchcasestheelsegoeswiththe closestpreviousun-else’edif.Thusinthiscase, theelsegoeswiththeinnerif,aswehaveindicatedbytheindentation. Itisawisepracticetoresolvesuchcasesby explicitbraces,justtomakeyourintentclear.In thecaseabove,wewouldwrite if(x>0){ if(y>0) write(6,1)x,y else write(6,2)y } whichdoesnotchangethemeaning,butleavesno -4-doubtinthereader’smind.Ifwewanttheother association,wemustwrite if(x>0){ if(y>0) write(6,1)x,y } else write(6,2)y The‘‘switch’’Statement Theswitchstatementprovidesacleanway toexpressmulti-waybrancheswhichbranchonthe valueofsomeinteger-valuedexpression.Thesyn-taxis switch(expression){ caseexpr1: statements caseexpr2,expr3: statements ... default: statements } Eachcaseisfollowedbyalistofcommaseparatedintegerexpressions.Theexpression insideswitchiscomparedagainstthecaseexpressionsexpr1,expr2,andsooninturnuntilone matches,atwhichtimethestatementsfollowing thatcaseareexecuted.Ifnocasesmatchexpression,andthereisadefaultsection,thestatementswithitaredone;ifthereisnodefault, nothingisdone.Inallsituations,assoonassome blockofstatementsisexecuted,theentireswitch isexitedimmediately.(ReadersfamiliarwithC[4] shouldbewarethatthisbehaviorisnotthesame astheCswitch.) The‘‘do’’Statement ThedostatementinRatforisquitesimilar totheDOstatementinFortran,exceptthatituses nostatementnumber.Thestatementnumber, afterall,servesonlytomarktheendoftheDO, andthiscanbedonejustaseasilywithbraces. Thus doi=1,n{ x(i)=0.0 y(i)=0.0 z(i)=0.0 } isthesameas do10i=1,n x(i)=0.0 y(i)=0.0 z(i)=0.0 10continue Thesyntaxis: dolegal-Fortran-DO-text Ratforstatement Thepartthatfollowsthekeyworddohastobe somethingthatcanlegallygointoaFortranDO statement.ThusifalocalversionofFortran allowsDOlimitstobeexpressions(whichisnot currentlypermittedinANSIFortran),theycanbe usedinaRatfordo. TheRatforstatementpartwilloftenbe enclosedinbraces,butaswiththeif,asingle statementneednothavebracesaroundit.This codesetsanarraytozero: doi=1,n x(i)=0.0 Slightlymorecomplicated, doi=1,n doj=1,n m(i,j)=0 setstheentirearraymtozero,and doi=1,n doj=1,n if(i<j) m(i,j)=−1 elseif(i==j) m(i,j)=0 else m(i,j)=+1 setstheuppertriangleofmto−1,thediagonalto zero,andthelowertriangleto+1.(Theoperator ==is‘‘equals’’,thatis,‘‘.EQ.’’.)Ineachcase,the statementthatfollowsthedoislogicallyasingle statement,eventhoughcomplicated,andthus needsnobraces. ‘‘break’’and‘‘next’’ Ratforprovidesastatementforleavinga loopearly,andoneforbeginningthenextiteration.breakcausesanimmediateexitfromthe do;ineffectitisabranchtothestatementafter thedo.nextisabranchtothebottomofthe loop,soitcausesthenextiterationtobedone. Forexample,thiscodeskipsovernegativevalues inanarray:

-5-doi=1,n{ if(x(i)<0.0) next processpositiveelement } breakandnextalsoworkintheotherRatfor loopingconstructionsthatwewilltalkaboutin thenextfewsections. breakandnextcanbefollowedbyanintegertoindicatebreakingoriteratingthatlevelof enclosingloop;thus break2 exitsfromtwolevelsofenclosingloops,and break1isequivalenttobreak.next2iterates thesecondenclosingloop.(Realistically,multilevelbreak’sandnext’sarenotlikelytobemuch usedbecausetheyleadtocodethatishardto understandandsomewhatriskytochange.) The‘‘while’’Statement OneoftheproblemswiththeFortranDO statementisthatitgenerallyinsistsuponbeing doneonce,regardlessofitslimits.Ifaloopbegins DOI=2,1 thiswilltypicallybedoneoncewithIsetto2, eventhoughcommonsensewouldsuggestthat perhapsitshouldn’tbe.OfcourseaRatfordo caneasilybeprecededbyatest if(j<=k) doi=j,k{ } butthishastobeaconsciousact,andisoften overlookedbyprogrammers. AmoreseriousproblemwiththeDOstatementisthatitencouragesthataprogrambewrittenintermsofanarithmeticprogressionwith smallpositivesteps,eventhoughthatmaynotbe thebestwaytowriteit.IfcodehastobecontortedtofittherequirementsimposedbytheFortranDO,itisthatmuchhardertowriteand understand. Toovercomethesedifficulties,Ratforprovidesawhilestatement,whichissimplyaloop: ‘‘whilesomeconditionistrue,repeatthisgroupof statements’’.Ithasnopreconceptionsaboutwhy oneislooping.Forexample,thisroutinetocomputesin(x)bytheMaclaurinseriescombinestwo terminationcriteria. realfunctionsin(x,e) #returnssin(x)toaccuracye,by #sin(x)=x−x∗∗3/3!+x∗∗5/5!−... sin=x term=x i=3 while(abs(term)>e&i<100){ term=−term∗x∗∗2/float(i∗(i−1)) sin=sin+term i=i+2 } return end Noticethatiftheroutineisenteredwith termalreadysmallerthane,theloopwillbedone zerotimes,thatis,noattemptwillbemadeto computex∗∗3andthusapotentialunderflowis avoided.Sincethetestismadeatthetopofa whileloopinsteadofthebottom,aspecialcase disappears—thecodeworksatoneofitsboundaries.(Thetesti<100istheotherboundary— makingsuretheroutinestopsaftersomemaximumnumberofiterations.) Asanaside,asharpcharacter‘‘#’’inaline marksthebeginningofacomment;therestofthe lineiscomment.Commentsandcodecanco-exist onthesameline—onecanmakemarginal remarks,whichisnotpossiblewithFortran’s‘‘Cin column1’’convention.Blanklinesarealsopermittedanywhere(theyarenotinFortran);they shouldbeusedtoemphasizethenaturaldivisions ofaprogram. Thesyntaxofthewhilestatementis while(legalFortrancondition) Ratforstatement Aswiththeif,legalFortranconditionissomething thatcangointoaFortranLogicalIF,andRatfor statementisasinglestatement,whichmaybemultiplestatementsinbraces. Thewhileencouragesastyleofcodingnot normallypracticedbyFortranprogrammers.For example,supposenextchisafunctionwhich returnsthenextinputcharacterbothasafunction valueandinitsargument.Thenalooptofindthe firstnon-blankcharacterisjust while(nextch(ich)==iblank) ; Asemicolonbyitselfisanullstatement,whichis necessaryheretomarktheendofthewhile;ifit werenotpresent,thewhilewouldcontrolthenext statement.Whentheloopisbroken,ichcontains thefirstnon-blank.Ofcoursethesamecodecan -6-bewritteninFortranas 100if(nextch(ich).eq.iblank)goto100 butmanyFortranprogrammers(andafewcompilers)believethislineisillegal.Thelanguageat one’sdisposalstronglyinfluenceshowonethinks aboutaproblem. The‘‘for’’Statement TheforstatementisanotherRatforloop, whichattemptstocarrytheseparationofloopbodyfromreason-for-loopingastepfurtherthan thewhile.Aforstatementallowsexplicitinitializationandincrementstepsaspartofthestatement.Forexample,aDOloopisjust for(i=1;i<=n;i=i+1)... Thisisequivalentto i=1 while(i<=n){ ... i=i+1 } Theinitializationandincrementofihavebeen movedintotheforstatement,makingiteasierto seeataglancewhatcontrolstheloop. Theforandwhileversionshavetheadvantagethattheywillbedonezerotimesifnisless than1;thisisnottrueofthedo. Theloopofthesineroutineintheprevious sectioncanbere-writtenwithaforas for(i=3;abs(term)>e&i<100;i=i+2){ term=−term∗x∗∗2/float(i∗(i−1)) sin=sin+term } Thesyntaxoftheforstatementis for(init;condition;increment) Ratforstatement initisanysingleFortranstatement,whichgets doneoncebeforetheloopbegins.incrementis anysingleFortranstatement,whichgetsdoneat theendofeachpassthroughtheloop,beforethe test.conditionisagainanythingthatislegalina logicalIF.Anyofinit,condition,andincrement maybeomitted,althoughthesemicolonsmust alwaysbepresent.Anon-existentconditionis treatedasalwaystrue,sofor(;;)isanindefinite repeat.(Butseetherepeat-untilinthenextsec-tion.) Theforstatementisparticularlyusefulfor backwardloops,chainingalonglists,loopsthat mightbedonezerotimes,andsimilarthingswhich arehardtoexpresswithaDOstatement,and obscuretowriteoutwithIF’sandGOTO’s.For example,hereisabackwardsDOlooptofindthe lastnon-blankcharacteronacard: for(i=80;i>0;i=i−1) if(card(i)!=blank) break (‘‘!=’’isthesameas‘‘.NE.’’).Thecodescansthe columnsfrom80throughto1.Ifanon-blankis found,theloopisimmediatelybroken.(break andnextworkinfor’sandwhile’sjustasin do’s).Ifireacheszero,thecardisallblank. Thiscodeisrathernastytowritewitha regularFortranDO,sincetheloopmustgoforward,andwemustexplicitlysetupproperconditionswhenwefalloutoftheloop.(Forgetting thisisacommonerror.)Thus: DO10J=1,80 I=81−J IF(CARD(I).NE.BLANK)GOTO11 10CONTINUE I=0 11... Theversionthatusestheforhandlestheterminationconditionproperlyforfree;iiszerowhenwe falloutoftheforloop. Theincrementinaforneednotbean arithmeticprogression;thefollowingprogram walksalongalist(storedinanintegerarrayptr) untilazeropointerisfound,addingupelements fromaparallelarrayofvalues: sum=0.0 for(i=first;i>0;i=ptr(i)) sum=sum+value(i) Noticethatthecodeworkscorrectlyifthelistis empty.Again,placingthetestatthetopofaloop insteadofthebottomeliminatesapotential boundaryerror. The‘‘repeat-until’’statement Inspiteofthedirewarnings,therearetimes whenonereallyneedsaloopthattestsatthebottomafteronepassthrough.Thisserviceisprovidedbytherepeat-until: repeat Ratforstatement until(legalFortrancondition) TheRatforstatementpartisdoneonce,thenthe conditionisevaluated.Ifitistrue,theloopis exited;ifitisfalse,anotherpassismade. Theuntilpartisoptional,soabarerepeat isthecleanestwaytospecifyaninfiniteloop.Of coursesuchaloopmustultimatelybebrokenby sometransferofcontrolsuchasstop,return,or break,oranimplicitstopsuchasrunningoutof -7-inputwithaREADstatement. Asamatterofobservedfact[8],therepeatuntilstatementismuchlessusedthantheother loopingconstructions;inparticular,itistypically outnumberedtentoonebyforandwhile.Be cautiousaboutusingit,forloopsthattestonlyat thebottomoftendon’thandlenullcaseswell. Moreonbreakandnext breakexitsimmediatelyfromdo,while, for,andrepeat-until.nextgoestothetestpart ofdo,whileandrepeat-until,andtotheincre-mentstepofafor. ‘‘return’’Statement ThestandardFortranmechanismforreturningavaluefromafunctionusesthenameofthe functionasavariablewhichcanbeassignedto; thelastvaluestoredinitisthefunctionvalue uponreturn.Forexample,hereisaroutineequal whichreturns1iftwoarraysareidentical,and zeroiftheydiffer.Thearrayendsaremarkedby thespecialvalue−1. #equalcomparestr1tostr2; #return1ifequal,0ifnot integerfunctionequal(str1,str2) integerstr1(100),str2(100) integeri for(i=1;str1(i)==str2(i);i=i+1) if(str1(i)==−1){ equal=1 return } equal=0 return end Inmanylanguages(e.g.,PL/I)oneinstead says return(expression) toreturnavaluefromafunction.Sincethisis oftenclearer,Ratforprovidessuchareturnstatement—inafunctionF,return(expression)is equivalentto {F=expression;return} Forexample,hereisequalagain:

#equalcomparestr1tostr2; #return1ifequal,0ifnot integerfunctionequal(str1,str2) integerstr1(100),str2(100) integeri for(i=1;str1(i)==str2(i);i=i+1) if(str1(i)==−1) return(1) return(0) end Ifthereisnoparenthesizedexpressionafter return,anormalRETURNismade.(Anotherversionofequalispresentedshortly.) Cosmetics Aswesaidabove,thevisualappearanceofa languagehasasubstantialeffectonhoweasyitis toreadandunderstandprograms.Accordingly, Ratforprovidesanumberofcosmeticfacilities whichmaybeusedtomakeprogramsmorereadable. Free-formInput Statementscanbeplacedanywhereona line;longstatementsarecontinuedautomatically, asarelongconditionsinif,while,for,anduntil. Blanklinesareignored.Multiplestatementsmay appearononeline,iftheyareseparatedbysemicolons.Nosemicolonisneededattheendofa line,ifRatforcanmakesomereasonableguess aboutwhetherthestatementendsthere.Lines endingwithanyofthecharacters =+−∗,|&( areassumedtobecontinuedonthenextline. Underscoresarediscardedwherevertheyoccur;all othersremainaspartofthestatement. AnystatementthatbeginswithanallnumericfieldisassumedtobeaFortranlabel,and placedincolumns1-5uponoutput.Thus write(6,100);100format("hello") isconvertedinto write(6,100) 100format(5hhello) TranslationServices Textenclosedinmatchingsingleordouble quotesisconvertedtonH...butisotherwiseunaltered(exceptforformatting—itmaygetsplit acrosscardboundariesduringthereformatting process).Withinquotedstrings,thebackslash‘\’ servesasanescapecharacter:thenextcharacteris takenliterally.Thisprovidesawaytogetquotes -8- (andofcoursethebackslashitself)intoquoted strings: "\\\′" isastringcontainingabackslashandanapostrophe.(Thisisnotthestandardconventionofdoubledquotes,butitiseasiertouseandmoregeneral.) Anylinethatbeginswiththecharacter‘%’ isleftabsolutelyunalteredexceptforstrippingoff the‘%’andmovingthelineonepositiontothe left.Thisisusefulforinsertingcontrolcards,and otherthingsthatshouldnotbetransmogrified (likeanexistingFortranprogram).Use‘%’only forordinarystatements,notforthecondition partsofif,while,etc.,ortheoutputmaycome outinanunexpectedplace. Thefollowingcharactertranslationsare made,exceptwithinsingleordoublequotesoron alinebeginningwitha‘%’. ==.eq.!=.ne. >.gt.>=.ge. <.lt.<=.le. &.and.|.or. !.not.¬.not. Inaddition,thefollowingtranslationsareprovided forinputdeviceswithrestrictedcharactersets. [{]} $({$)} ‘‘define’’Statement Anystringofalphanumericcharacterscan bedefinedasaname;thereafter,wheneverthat nameoccursintheinput(delimitedbynonalphanumerics)itisreplacedbytherestofthe definitionline.(Commentsandtrailingwhite spacesarestrippedoff).Adefinednamecanbe arbitrarilylong,andmustbeginwithaletter. defineistypicallyusedtocreatesymbolic parameters: defineROWS100 defineCOLS50 dimensiona(ROWS),b(ROWS,COLS) if(i>ROWS|j>COLS)... Alternately,definitionsmaybewrittenas define(ROWS,100) Inthiscase,thedefiningtextiseverythingafter thecommauptothebalancingrightparenthesis; thisallowsmulti-linedefinitions. Itisgenerallyawisepracticetousesymbolicparametersformostconstants,tohelpmake clearthefunctionofwhatwouldotherwisebe mysteriousnumbers.Asanexample,hereisthe routineequalagain,thistimewithsymbolicconstants. defineYES1 defineNO0 defineEOS−1 defineARB100 #equalcomparestr1tostr2; #returnYESifequal,NOifnot integerfunctionequal(str1,str2) integerstr1(ARB),str2(ARB) integeri for(i=1;str1(i)==str2(i);i=i+1) if(str1(i)==EOS) return(YES) return(NO) end ‘‘include’’Statement Thestatement includefile insertsthefilefoundoninputstreamfileintothe Ratforinputinplaceoftheincludestatement. ThestandardusageistoplaceCOMMONblockson afile,andincludethatfilewheneveracopyis needed: subroutinex includecommonblocks ... end suroutiney includecommonblocks ... end ThisensuresthatallcopiesoftheCOMMONblocks areidentical Pitfalls,Botches,BlemishesandotherFailings Ratforcatchescertainsyntaxerrors,suchas missingbraces,elseclauseswithoutanif,and mosterrorsinvolvingmissingparenthesesinstatements.Beyondthat,sinceRatforknowsnoFortran,anyerrorsyoumakewillbereportedbythe Fortrancompiler,soyouwillfromtimetotime havetorelateaFortrandiagnosticbacktothe Ratforsource. Keywordsarereserved—usingif,else,etc., asvariablenameswilltypicallywreakhavoc. Don’tleavespacesinkeywords.Don’tusethe ArithmeticIF.

-9-TheFortrannHconventionisnotrecog-nizedanywherebyRatfor;usequotesinstead. 3.IMPLEMENTATION RatforwasoriginallywritteninC[4]onthe UNIXoperatingsystem[5].Thelanguageisspecifiedbyacontextfreegrammarandthecompiler constructedusingtheYACCcompiler-compiler[6]. TheRatforgrammarissimpleandstraightforward,beingessentially prog:stat |progstat stat:if(...)stat |if(...)statelsestat |while(...)stat |for(...;...;...)stat |do...stat |repeatstat |repeatstatuntil(...) |switch(...){case...:prog... default:prog} |return |break |next |digitsstat |{prog} |anythingunrecognizable TheobservationthatRatforknowsnoFortranfollowsdirectlyfromtherulethatsaysastatementis ‘‘anythingunrecognizable’’.InfactmostofFortranfallsintothiscategory,sinceanystatement thatdoesnotbeginwithoneofthekeywordsisby definition‘‘unrecognizable.’’ Codegenerationisalsosimple.Ifthefirst thingonasourcelineisnotakeyword(likeif, else,etc.)theentirestatementissimplycopiedto theoutputwithappropriatecharactertranslation andformatting.(Leadingdigitsaretreatedasa label.)Keywordscauseonlyslightlymorecomplicatedactions.Forexample,whenifisrecognized, twoconsecutivelabelsLandL+1aregenerated andthevalueofLisstacked.Theconditionis thenisolated,andthecode if(.not.(condition))gotoL isoutput.Thestatementpartoftheifisthen translated.Whentheendofthestatementis encountered(whichmaybesomedistanceaway andincludenestedif’s,ofcourse),thecode Lcontinue isgenerated,unlessthereisanelseclause,in whichcasethecodeis gotoL+1 Lcontinue Inthislattercase,thecode L+1continue isproducedafterthestatementpartoftheelse. Codegenerationforthevariousloopsisequally simple. Onemightarguethatmorecareshouldbe takenincodegeneration.Forexample,ifthereis notrailingelse, if(i>0)x=a shouldbeleftalone,notconvertedinto if(.not.(i.gt.0))goto100 x=a 100continue Butwhatareoptimizingcompilersfor,ifnotto improvecode?Itisarareprogramindeedwhere thiskindof‘‘inefficiency’’willmakeevenameasurabledifference.Inthefewcaseswhereitis important,theoffendinglinescanbeprotectedby ‘%’. Theuseofacompiler-compilerisdefinitely thepreferredmethodofsoftwaredevelopment. Thelanguageiswell-defined,withfewsyntactic irregularities.Implementationisquitesimple;the originalconstructiontookunderaweek.Thelanguageissufficientlysimple,however,thatanad hocrecognizercanbereadilyconstructedtodothe samejobifnocompiler-compilerisavailable. TheCversionofRatforisusedonUNIXand ontheHoneywellGCOSsystems.Ccompilersare notaswidelyavailableasFortran,however,so thereisalsoaRatforwritteninitselfandoriginallybootstrappedwiththeCversion.TheRatforversionwaswrittensoastotranslateintothe portablesubsetofFortrandescribedin[1],soitis portable,havingbeenrunessentiallywithout changeonatleasttwelvedistinctmachines.(The mainrestrictionsoftheportablesubsetare:only onecharacterpermachineword;subscriptsinthe formc∗v±c;avoidingexpressionsinplaceslikeDO loops;consistencyinsubroutineargumentusage, andinCOMMONdeclarations.Ratforitselfwillnot gratuitouslygeneratenon-standardFortran.) TheRatforversionisabout1500linesof Ratfor(comparedtoabout1000linesofC);this compilesinto2500linesofFortran.Thisexpansionratioissomewhathigherthanaverage,since thecompiledcodecontainsunnecessaryoccurrencesofCOMMONdeclarations.Theexecution timeoftheRatforversionisdominatedbytwo routinesthatreadandwritecards.Clearlythese routinescouldbereplacedbymachinecodedlocal versions;unlessthisisdone,theefficiencyofother partsofthetranslationprocessislargelyirrelevant.

-10-4.EXPERIENCE GoodThings ‘‘It’ssomuchbetterthanFortran’’isthe mostcommonresponseofuserswhenaskedhow wellRatformeetstheirneeds.Althoughcynics mightconsiderthistobevacuous,itdoesseemto betruethatdecentcontrolflowandcosmeticsconvertsFortranfromabadlanguageintoquiteareasonableone,assumingthatFortrandatastructures areadequateforthetaskathand. Althoughtherearenoquantitativeresults, usersfeelthatcodinginRatforisatleasttwiceas fastasinFortran.Moreimportant,debugging andsubsequentrevisionaremuchfasterthanin Fortran.Partlythisissimplybecausethecode canberead.Theloopingstatementswhichtestat thetopinsteadofthebottomseemtoeliminateor atleastreducetheoccurrenceofawideclassof boundaryerrors.Andofcourseitiseasytodo structuredprogramminginRatfor;thisselfdisciplinealsocontributesmarkedlytoreliability. Oneinterestingandencouragingfactisthat programswritteninRatfortendtobeasreadable asprogramswritteninmoremodernlanguages likePascal.Onceoneisfreedfromtheshacklesof Fortran’sclericaldetailandrigidinputformat,it iseasytowritecodethatisreadable,evenestheticallypleasing.Forexample,hereisaRatfor implementationofthelineartablesearchdiscussed byKnuth[7]: A(m+1)=x for(i=1;A(i)!=x;i=i+1) ; if(i>m){ m=i B(i)=1 } else B(i)=B(i)+1 Alargecorpus(5400lines)ofRatfor,includinga subsetoftheRatforpreprocessoritself,canbe foundin[8]. BadThings Thebiggestsingleproblemisthatmany FortransyntaxerrorsarenotdetectedbyRatfor butbythelocalFortrancompiler.Thecompiler thenprintsamessageintermsofthegenerated Fortran,andinafewcasesthismaybedifficultto relatebacktotheoffendingRatforline,especially iftheimplementationconcealsthegeneratedFortran.Thisproblemcouldbedealtwithbytagging eachgeneratedlinewithsomeindicationofthe sourcelinethatcreatedit,butthisisinherently implementation-dependent,sonoactionhasyet beentaken.Errormessageinterpretationis actuallynotsoarduousasmightbethought. SinceRatforgeneratesnovariables,onlyasimple patternofIF’sandGOTO’s,data-relatederrorslike missingDIMENSIONstatementsareeasytofindin theFortran.Furthermore,therehasbeenasteady improvementinRatfor’sabilitytocatchtrivial syntacticerrorslikeunbalancedparenthesesand quotes. Thereareanumberofimplementation weaknessesthatareanuisance,especiallytonew users.Forexample,keywordsarereserved.This rarelymakesanydifference,exceptforthosehardy soulswhowanttouseanArithmeticIF.Afew standardFortranconstructionsarenotaccepted byRatfor,andthisisperceivedasaproblemby userswithalargecorpusofexistingFortranprograms.Protectingeverylinewitha‘%’isnot reallyacompletesolution,althoughitservesasa stop-gap.Thebestlong-termsolutionisprovided bytheprogramStruct[9],whichconvertsarbitraryFortranprogramsintoRatfor. Userswhoexportprogramsoftencomplain thatthegeneratedFortranis‘‘unreadable’’ becauseitisnottastefullyformattedandcontains extraneousCONTINUEstatements.Tosomeextent thiscanbeameliorated(Ratfornowhasanoption tocopyRatforcommentsintothegeneratedFortran),butithasalwaysseemedthateffortisbetterspentontheinputlanguagethanontheoutputesthetics. Onefinalproblemispartlyattributableto success—sinceRatforisrelativelyeasytomodify, therearenowseveraldialectsofRatfor.Fortunately,sofarmostofthedifferencesareincharacterset,orininvisibleaspectslikecodegeneration. 5.CONCLUSIONS Ratfordemonstratesthatwithmodesteffort itispossibletoconvertFortranfromabadlanguageintoquiteagoodone.Apreprocessoris clearlyausefulwaytoextendoramelioratethe facilitiesofabaselanguage. Whendesigningalanguage,itisimportant toconcentrateontheessentialrequirementofprovidingtheuserwiththebestlanguagepossiblefor agiveneffort.Onemustavoidthrowingin‘‘features’’—thingswhichtheusermaytriviallyconstructwithintheexistingframework. Onemustalsoavoidgettingsidetrackedon irrelevancies.Forinstanceitseemspointlessfor Ratfortoprepareaneatlyformattedlistingof eitheritsinputoritsoutput.Theuserispresumablycapableoftheself-disciplinerequiredtopre-pareneatinputthatreflectshisthoughts.Itis muchmoreimportantthatthelanguageprovide free-forminputsohecanformatitneatly.Noone shouldreadtheoutputanywayexceptinthemost -11-direcircumstances. Acknowledgements C.A.R.Hoareoncesaidthat‘‘Onething [thelanguagedesigner]shouldnotdoistoinclude untriedideasofhisown.’’Ratforfollowsthispreceptveryclosely—everythinginithasbeen stolenfromsomeoneelse.Mostofthecontrolflow structuresaretakendirectlyfromthelanguage C[4]developedbyDennisRitchie;thecomment andcontinuationconventionsareadaptedfrom Altran[10]. IamgratefultoStuartFeldman,whose patientsimulationofaninnocentuserduringthe earlydaysofRatforledtoseveraldesign improvementsandtheeradicationofbugs.He alsotranslatedtheCparse-tablesandYACCparser intoFortranforthefirstRatforversionofRatfor. References [1]B.G.Ryder,‘‘ThePFORTVerifier,’’Software—Practice&Experience,October1974. [2]AmericanNationalStandardFortran. AmericanNationalStandardsInstitute,New York,1966. [3]For-word:FortranDevelopmentNewsletter, August1975. [4]B.W.KernighanandD.M.Ritchie,TheC ProgrammingLanguage,Prentice-Hall,Inc., 1978. [5]D.M.RitchieandK.L.Thompson,‘‘The UNIXTime-sharingSystem.’’CACM,July 1974. [6]S.C.Johnson,‘‘YACC—YetAnother Compiler-Compiler.’’BellLaboratories ComputingScienceTechnicalReport#32, 1978. [7]D.E.Knuth,‘‘StructuredProgramming withgotoStatements.’’ComputingSurveys, December1974. [8]B.W.KernighanandP.J.Plauger,SoftwareTools,Addison-Wesley,1976. [9]B.S.Baker,‘‘Struct—AProgramwhich StructuresFortran’’,BellLaboratoriesinternalmemorandum,December1975. [10]A.D.Hall,‘‘TheAltranSystemforRational FunctionManipulation—ASurvey.’’ CACM,August1971.

-12-Appendix:UsageonUNIXandGCOS. Beware—localcustomsvary.Checkwithanativebeforegoingintothejungle. UNIX Theprogramratforisthebasictranslator;ittakeseitheralistoffilenamesorthestandardinput andwritesFortranonthestandardoutput.Optionsinclude−6x,whichusesxasacontinuationcharacter incolumn6(UNIXuses&incolumn1),and−C,whichcausesRatforcommentstobecopiedintothegeneratedFortran. Theprogramrcprovidesaninterfacetotheratforcommandwhichismuchthesameascc.Thus rc[options]files compilesthefilesspecifiedbyfiles.Fileswithnamesendingin.rareRatforsource;otherfilesareassumed tobefortheloader.Theflags−Cand−6xdescribedabovearerecognized,asare −ccompileonly;don′tload −fsaveintermediateFortran.ffiles −rRatforonly;implies−cand−f −2usebigFortrancompiler(forlargeprograms) −Uflagundeclaredvariables(notuniversallyavailable) Otherflagsarepassedontotheloader. GCOS Theprogram./ratforisthebaretranslator,andisidenticaltotheUNIXversion,exceptthatthecontinuationconventionis&incolumn6.Thus ./ratforfiles>output translatestheRatforsourceonfilesandcollectsthegeneratedFortranonfile‘output’forsubsequentprocessing. ./rcprovidesmuchthesameservicesasrc(withinthelimitationsofGCOS),regrettablywithasomewhatdifferentsyntax.Optionsrecognizedby./rcinclude nameRatforsourceorlibrary,dependingontype h=/namemakeTSSH∗file(runnableversion);runas/name r=/nameupdateanduserandomlibrary a=compileasascii(defaultisbcd) C=copycommentsintoFortran f=nameFortransourcefile g=namegmapsourcefile Otheroptionsareasspecifiedforthe./cccommanddescribedin[4]. TSO,TSS,andothersystems Ratforexistsonvariousothersystems;checkwiththeauthorforspecifics.ratfor:nroff-Tdvi -mgsm∗>ratfor.dvi