a tutorial on programming features in...

145

Upload: others

Post on 31-May-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 2: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

ATutorialonProgrammingFeaturesinATSHongweiXi

<gmhwxiATgmailDOTcom>

Copyright©2010-201?HongweiXi

Allrightsarereserved.Permissionisgrantedtoprintthisdocumentforpersonaluse.

TableofContentsPrefaceI.BasicTutorialTopics

1.Syntax-ColoringforATScode2.FilenameExtensions3.FileInclusioninsideATSCode4.FixityDeclarations5.StaticLoad6.DynamicLoad7.BracketOverloading8.Dot-SymbolOverloading9.Recursion10.Datatypes11.FunctionalLists12.FunctionalSetsandMaps

FunctionalSetsFunctionalMaps

13.Exceptions14.References15.PersistentArrays16.PersistentArrays-with-size17.PersistentMatrices18.PersistentMatrices-with-size19.PersistentHashtables20.Tail-Recursion21.Higher-OrderFunctions

Page 3: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

22.Stream-BasedLazyEvaluation23.LinearlyTypedLists

II.AdvancedTutorialTopics24.Extvar-Declaration25.LinearClosure-Functions26.AutomaticCodeGeneration

Generatingadatcon-functionGeneratingadatcontag-functionGeneratingafprint-function

Page 4: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

PrefaceThistutorialcoversavarietyofissuesthataprogrammertypicallyencounterswhenprogramminginATS. It is written mostly in the style of learn-by-examples. Although it is possible to learnprogramminginATSbystudyingthetutorial(ifthereaderisfamiliarwithMLandC),IconsiderthebookIntroductiontoProgramminginATSafarmoreapproriatesourceforsomeonetoacquireaviewofATSinacoherentandsystematicmanner.Ofcourse,therewillalsobeconsiderableamountof overlapping between these two books. The primary purpose of the tutorial is to bring moreinsights into a rich set of programming features in ATS and also demonstrate through concreteexamples that these features can be made of effective use in the construction of high-qualityprograms.

Page 5: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

I.BasicTutorialTopicsTableofContents1.Syntax-ColoringforATScode2.FilenameExtensions3.FileInclusioninsideATSCode4.FixityDeclarations5.StaticLoad6.DynamicLoad7.BracketOverloading8.Dot-SymbolOverloading9.Recursion10.Datatypes11.FunctionalLists12.FunctionalSetsandMaps13.Exceptions14.References15.PersistentArrays16.PersistentArrays-with-size17.PersistentMatrices18.PersistentMatrices-with-size19.PersistentHashtables20.Tail-Recursion21.Higher-OrderFunctions22.Stream-BasedLazyEvaluation23.LinearlyTypedLists

Page 6: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 7: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 8: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter1.Syntax-ColoringforATScodeThesyntaxofATSishighlyinvolved,whichcanbeadauntingobstacleforbeginnerstryingtoreadandwriteATScode.Inordertoalleviatethisproblem,ImayemploycolorstodifferentiatevarioussyntacticalentitiesinATScode.TheconventionIadoptforcoloringATSsyntaxisgivenasfollows:

ThekeywordsinATSareallcoloredblack(andpossiblywritteninboldface).

ThecommentsinATSareallcoloredgray.

ThecodeinthestaticsofATSiscoloredblue.

ThecodeinthedynamicsofATSiscoloredredunlessitrepresentsproofs,forwhichthecolordarkgreenisused.

Theexternalcode(inC)iscoloreddeepbrown.

PleasefindanexampleofATScodeon-linethatinvolvesallofthesyntax-coloringmentionedabove.

Page 9: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 10: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 11: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter2.FilenameExtensionsIn ATS, the filename extensions .sats and .dats are reserved to indicate static and dynamic files,respectively. As these two extensions have some special meaning attached to them, which can beinterpretedbythecommandatscc,theyshouldnotbereplacedarbitrarily.

A static file may contain sort definitions, datasort declarations, static definitions, abstract typedeclarations,exceptiondeclarations,datatypedeclarations,macrodefinitions,interfacesfordynamicvaluesandfunctions,etc.Intermsoffunctionality,astaticfileinATSissomewhatsimilartoaheaderfile(withtheextension.h)inCoraninterfacefile(withtheextension.mli)inOCaml.

Adynamicfilemaycontaineverythinginastaticfile.Inaddition,itmayalsocontaindefinitionsfordynamicvaluesandfunctions.However,interfacesforfunctionsandvaluesinadynamicfileshouldfollowthekeyword extern ,whichontheotherhandshouldnotbepresentwhensuchinterfacesaredeclaredinastaticfile.Forinstance,thefollowingsyntaxdeclaresinterfaces(ortypes)inastaticfileforavaluenamed pi andafunctionnamed area_of_circle :

valpi:double

funarea_of_circle(radius:double):double

When the same interfaces are declared in a dynamic file, the following slightly different syntaxshouldbeused:

externvalpi:double

externfunarea_of_circle(radius:double):double

Pleasenote that a static file is essentially a special caseof adynamic file. It is entirelypossible toreplaceastaticfilewithadynamicone.

Asaconvention,weoftenusethefilenameextension.catstoindicatethatafilecontainssomeCcodethat is supposed to be combined with ATS code in certain manner. There is also the filenameextension.hats,whichweoccassionallyuseforafilethatshouldbeincludedinATScodestoredinanotherfile.However,theuseofthesetwofilenameextensionsarenotmandatory,thatis,theycanbereplacedifneededorwanted.

Page 12: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 13: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 14: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter3.FileInclusioninsideATSCodeAs is in C, file inclusion inside ATS code is done through the use of the directive #include. Forinstance, the following line indicates that a file named foobar is included, that is, this line is to bereplacedwiththecontentofthefilefoobar:

#include"foobar.hats"

Note that the included file is parsed according to the syntax for statics or dynamics depending onwhetherthefileisincludedinastaticordynamicfile.Asaconvention,thenameofanincludedfileoftenendswiththeextension.hats.

A common use of file inclusion is to keep some constants, flags or parameters being definedconsistently across a set of files.For instance, the fileprelude/params.hats serves such a purpose.Fileinclusioncanalsobeusedtoemulate(inalimitedbutratherusefulmanner)functorssupportedinlanguagessuchasSMLandOCaml.

Page 15: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 16: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 17: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter4.FixityDeclarationsGivenafunctionf,thestandardsyntaxforapplyingftoanargumentvisf(v);fortwoargumentsv1andv2, thesyntaxis f(v1,v2).Also, it isallowedinATStouse infixnotationforabinaryfunctionapplication,andprefix/postifixnotationforaunaryfunctionapplication.

Each identifier inATS can be assigned one of the following fixities:prefix, infix andpostfix. Thefixitydeclarationsformanycommonlyusedidentifierscanbefoundinprelude/fixity.ats.Often, thenameoperator is used to refer to an identifier that is assigneda fixity.For instance, the followingsyntaxdeclaresthat + and - areinfixoperatorsofaprecedencevalueequalto50:

infixl50+-

Afterthisdeclaration,wecanwriteanexpressionlike 1+2-3 ,whichisparsedinto -(+(1,2),3)intermsofthestandardsyntaxforfunctionapplication.

The keyword infixl indicates that the declared infix operators are left-associative. For right-associative and non-associative infix operators, please use the keywords infixr and infix ,respectively.Iftheprecedencevalueisomittedinafixitydeclaration,itisassumedtobeequalto0.

Wecanalsousethefollowingsyntaxtodeclarethat iadd , fadd , padd and uadd are left-associativeinfixoperatorswithaprecedencevalueequaltothatoftheoperator + :

infixl(+)iaddfaddpadduadd

Thisisusefulasitisdifficultinpracticetoremembertheprecedencevaluesof(alargecollectionof)declaredoperators.Sometimes,wemayneedtospecifythattheprecedencevalueofoneoperatorinrelation to that of another one. For instance, the following syntax declares that opr2 is a left-associativeinfixoperatoranditsprecedencevalueisthatof opr1 plus10:

infixl(opr1+10)opr2

Iftheplussign(+)ischangedtotheminussign(-),thentheprecedencevalueof opr2 isthatof opr1minus10.

Wecanalsoturnanidentifier opr intoanon-associative infixoperator (ofprecedencevalue0)byputtingthebackslashsymbol( \ )infrontofit.Forinstance,theexpression exp1\oprexp2 standsforopr(exp1,exp2) ,where exp1 and exp2 refertosomeexpressions,eitherstaticordynamic.

Page 18: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Thesyntaxfordeclaring(unary)prefixandpostfixoperatorsaresimilar.Forinstance,thefollowingsyntax declares that ~ and ? are prefix and postfix operators of precedence values 61 and 69,respectively:

prefix61~

postfix69?

Asanexample,apostfixoperatorisinvolvedinthefollowing3-lineprogram:

postfix(imul+10)!!

externfun!!(x:int):int

implement!!(x)=ifx>=2thenx*(x-2)!!else1

Foragivenoccurrenceofanoperator,wecandepriveitofitsassignedfixitystatusbysimplyputtingthekeyword op infrontofit.Forinstance 1+2-3 canbewritenas op-(op+(1,2),3) .Itisalsopossibleto(permanently)depriveanoperatorofitsassignedfixitystatus.Forinstance,thefollowingsyntaxdoessototheoperators iadd , fadd , padd and uadd :

nonfixiaddfaddpadduadd

Notethat nonfix isakeywordinATS.

Lastly,pleasenotethateachfixitydeclarationisonlyeffectivewithinitsownlegalscope.

Page 19: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 20: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 21: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter5.StaticLoadInATS, static load (or staload for short) refers to the creation of a namespace populatedwith thedeclarednamesinaloadedpackage.

Supposethatafilenamedfoo.satscontainsthefollowingcode:

//

datatype

aDatatype=

|A|Bof(int,int)

//

valaValue:int

funaFunction:int->int

//

Thefollowingstaload-declarationintroducesanamespace FOO forthenamesdeclaredinfoo.sats:

staloadFOO="foo.sats"

Theprefix $FOO. needstobeattachedtoanameinthenamespace FOO inorderforittobereferenced.Forinstance,thenamesavailableinthenamespace FOO areallreferencedinthefollowingcode:

vala:$FOO.aDatatype=$FOO.A()

valb:$FOO.aDatatype=$FOO.B(0,$FOO.aFunction($FOO.aValue))

Ifthefilefoo.satsisstaloadedasfollowsforthesecondtime:

staloadFOO2="foo.sats"

thenfoo.satsisnotactuallyloadedbythecompiler.Instead, FOO2 issimplymadetobeanaliasof

FOO .

Itisalsoallowedforfoo.satstobestaloadedasfollows:

staload"foo.sats"

Inthiscase,thenamespaceforthenamesdeclaredinfoo.satsisopened.Forinstance,thefollowing

codeshowsthatthesenamescannowbereferenceddirectly:

vala:aDatatype=A()

Page 22: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

valb:aDatatype=B(0,aFunction(aValue))

Letussupposethatwehavethefollowingsequenceofdeclarations:

valaValue=0

staload"foo.sats"

valanotheValue=aValue+1

Doesthesecondoccurrenceof aValue refertotheoneintroducedinthefirstdeclaration,oritrefersto the one declared inside foo.sats? The answer may be a bit surprising: It refers to the one

introducedin thefirstdeclarationasabindingfor theoccurrenceofanameisresolvedinATSbysearchingfirstthroughtheavailablenamesdelcaredinthesamefile.

Page 23: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 24: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 25: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter6.DynamicLoadIn ATS, dynamic load (or dynload for short) refers to some form of initialization of a loadedpackage.

Supposethatafilenamedfoo.datscontainsthefollowingcode:

//

valx=1000

valy=x+x//=2000

valz=y*y//=4000000

//

extern

funsum_x_y_z():int

//

implementsum_x_y_z()=x+y+z

//

Clearly,thenamesx,y,andzmustbeboundtosomevaluesbeforeacalltothefunction sum_x_y_zcan be evaluated. In order to create such bindings, some form of initialization is required. Let usfurthersupposethatafilenamedfoo2.datscontainsthefollowingcode:

staload"./foo.dats"

dynload"./foo.dats"//forinitialization

implement

main0()=

{

val()=assertloc(4003000=sum_x_y_z())

}(*endof[main0]*)

Wecannowgenerateanexecutablefilemytestbyissuingthefollowingcommand-line:

atscc-omytestfoo.datsfoo2.dats

Notethatatsccmayneedtobechangedtopatscc.

Thelinestartingwiththekeyword dynload isreferredtoasadynload-declaration.Ifitisdeletedfromthefilefoo2.dats,thenexecutingtheabovecommand-lineleadstolink-timereportingofundefined

referencetoavariableofcertainnameendingwiththestring__dynloadflag.Thedynload-declarationforfoo.dats introduces thisspecialvariableand thenmakesacall toaspecial functionassociated

Page 26: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

withfoo.dats for thepurposeofperforming some formof initialization.This special function is

referredasadynload-function(forfoo.dats),whichisalwaysidempotent.

There is also a dynload-function generated forfoo2.dats.As the function main0 , a variant of the

special function main , is implemented in foo2.dats, the dynload-function for foo2.dats is

automaticallycalledinsidethebodyofthe main function.

Ifthereisareasontosuppressthegenerationofadynload-function,onecansetthevalueoftheflagATS_DYNLOADFLAG to0.For instance,nodynload-function forfoo.dats is generated if the following

lineisaddedintofoo.dats:

#defineATS_DYNLOADFLAG0

Ofcourse,skippingproperinitializationforfoo.datsmeansthatanerroneousresultisexpectedif

thefunction sum_x_y_z isevercalled.

Ifthereisareasontocallthedynload-functionforfoo2.datsexplicitly,onecanintroduceanalias

foritandthencallthealias.Forinstance,ifthefollowinglineisaddedtofoo2.dats:

#defineATS_DYNLOADNAME"foo2_dynload"

thenthedynload-functionforfoo2.datsisgivenanalias foo2_dynload .

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 27: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 28: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 29: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter7.BracketOverloadingInmanyprogramminglanguages,bracket-notationiscommonlyassociatedwitharraysubscripting.Forinstance, A[i] isaleft-valueinCthatreferstoarray-cell i inthearrayreferredtoby A .ThereissupportinATSforoverloadingbracketswithmultiplefunctionnamessothatbracket-notationcanbeemployedtocallthesefunctions,resultingincodethatreadslikesomeformofsubscripting.Itisexpectedthatthisstyleofcallingfunctionscan,sometimes,makethecodewritteninATSmoreeasilyaccessible.

Letusnowseeasimpleexampleofbracket-notationinoverloading.Inthefollowngcode,alinearabstracttype lock isintroducedtogetherwithtwofunctions:

//

absvtypelock(a:vt@ype)

//

extern

fun{a:vt0p}lock_acquire(!lock(a)):a

extern

fun{a:vt0p}lock_release(!lock(a),a):void

//

As one can imagine, lock_acquire is called to obtain the value stored in a given lock whilelock_release iscalledtoreturnavaluetoagivenlock.

Supposethatwenowintroducethefollowingoverloadingdeclarations:

//

overload[]withlock_acquire

overload[]withlock_release

//

Withthesedeclarations,thefollowingcodetypechecks:

//

val

mylock=$extval(lock(int),"mylock")

//

valx0=mylock[]//=lock_acquire(mylock)

val()=mylock[]:=x0//=lock_release(mylock,x0)

//

Page 30: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Notethatthebracket-notationinanyassigementisonlyallowedtorefertoafunctionthatreturnsthevoid-value.Intheaboveexample,thefunction lock_release returnsthevoid-value.

InATS, bracket-notation is already overloadedwith functions performing list-subscripting, array-subscriptingandmatrix-subscripting,anditcanalsobeusedtoaccessandupdateagivenreference.

Pleasefindon-linetheentiretyofthecodepresentedinthischapter.

Page 31: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 32: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 33: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter8.Dot-SymbolOverloadingInmanyprogramminglanguages,theso-calleddot-notationiscommonlyassociatedwithselectingafield from a given tuple-value, record-value or object-value. In ATS, field selection can be donethrough either pattern matching or the use of dot-notation. For example, the following codeconstructsaflattupleandalsoaboxedone,andthenusesdot-notationtoselecttheircomponents:

//

valtup_flat=@("a","b")

valtup_boxed=$tup("a","b")

//

val-"a"=tup_flat.0and"b"=tup_flat.1

val-"a"=tup_boxed.0and"b"=tup_boxed.1

//

ThereissupportinATSforoverloadingaspecifieddot-symbolwithmultiplefunctionnamessothatdot-notationcanbeemployedtocallthesefunctions,resultingincodethatreadslikefieldselectionfromtuplesorrecords.Thisstyleofcallingfunctionscan,sometimes,makethecodewritteninATSmoreeasilyaccessible,anditisespeciallysowhenATSinteractswithlanguagesthatsupportobject-orientedprogramming.

Asanexampleofdot-notation inoverloading, letus introduceanon-linearabstract type point forpointsina2-dimensionalspaceandalsodeclaresomeassociatedfunctions:

//

abstypepoint=ptr//boxed

//

extern

fun

point_make

(x:double,y:double):point

//

extern

funpoint_get_x(p:point):double

andpoint_get_y(p:point):double

//

extern

funpoint_set_x(p:point,x:double):void

andpoint_set_y(p:point,x:double):void

//

For getting the x-coordinate and y-coordinate of a given point, the functions point_get_x and

Page 34: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

point_get_y canbecalled,respectively.Forsettingthex-coordinateandy-coordinateofagivenpoint,thefunctions point_set_x and point_set_y canbecalled,respectively.Byintroducingtwodot-symbols.x and .y andthenoverloadingthemwithcertainfunctionnamesasfollows:

symintr.x.y

overload.xwithpoint_get_x

overload.xwithpoint_set_x

overload.ywithpoint_get_y

overload.ywithpoint_set_y

wecanusedot-notationtocall thecorrespondingget-functionsandset-functionsasisshowninthefollowingcode:

valp0=point_make(1.0,~1.0)

valx0=p0.x()//point_get_x(p0)

andy0=p0.y()//point_get_y(p0)

val()=p0.x:=y0//point_set_x(p0,y0)

and()=p0.y:=x0//point_set_y(p0,x0)

Notethatwriting p0.x for p0.x() iscurrentlynotsupported.Thedot-notation inanyassigement isonlyallowedtorefertoafunctionthatreturnsthevoid-value.Intheaboveexample,both point_set_xand point_set_y returnthevoid-value.

Letusintroducealinearabstracttype counter forcounterobjectsandafewfunctionsassociatedwithit:

//

absvtypecounter=ptr

//

extern

funcounter_make():counter

extern

funcounter_free(counter):void

//

extern

funcounter_get(cntr:!counter):int

extern

funcounter_incby(cntr:!counter,n:int):void

//

As can be expected, the functions counter_make and counter_free are for creating and destroying acounter object, respectively. The function counter_get returns the current count stored in a give

Page 35: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

counter,andthefunction counter_incby increasethatcountbyagivenintegervalue.

Letusintroducethefollowingoverloadingdeclarations:

//

overload.getwithcounter_get

overload.incbywithcounter_incby

//

Asisexpected,onecannowcall counter_get asfollows:

valn0=c0.get()//=counter_get(c0)

Similarly,onecancall counter_incby asfollowstoincreasethecountstoredin c0 by1:

val()=c0.incby(1)//=counter_incby(c0,1)

Ifwerevisit thepreviousexampleinvolving(non-linear)points, thenwecanseethat thefollowingcodealsotypechecks:

valp0=point_make(1.0,~1.0)

valx0=p0.x()//point_get_x(p0)

andy0=p0.y()//point_get_y(p0)

val()=p0.x(y0)//point_set_x(p0,y0)

and()=p0.y(x0)//point_set_y(p0,x0)

Imayusethephrasefunctionaldot-notationtorefertothisformofdot-notationsoastodifferentiateitfromthegeneralformofdot-notation.

Pleasefindon-linetheentiretyofthecodepresentedinthischapterplussometestingcode.

Page 36: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 37: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 38: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter9.RecursionThe notion of recursion is ubiquitous in ATS. For instance, there are recursively defined sorts(datasorts)andtypes(datatypes)inthestatics,andtherearealsorecursivelydefinedfunctionsinthedynamics. Literally, the word recurse means "go back". When an entity is defined recursively, itmeansthat theentitybeingdefinedcanappear in itsowndefinition.Inthefollowingpresentation,Iwill show severalways to define (or implement) recursive functions and non-recursive functions,wherethelatterisjustaspecialcaseoftheformer.

Thekeyword fun canbeusedtoinitiatethedefinitionofarecursivefunction.Forinstance,followingisthedefinitionofarecursivefunction:

fun

fact(x:int):int=

ifx>0thenx*fact(x-1)else1

(*endof[fact]*)

Anon-recursivefunctionisaspecialkindofrecursivefunctionthatdoesmakeuseofitselfinitsowndefinition. So one can certainly use fun to initiate the definition of a non-recursive function.However, if thereisaneedtoindicateexplicitlythatanon-recursiveisbeingdefined,thenonecanuse the keyword fn to do so. For instance, the definiton of a non-recursive function is given asfollows:

fnsquare(x:int):int=x*x

whichisdirectlytranslatedbythecompilerintothefollowingbindingbetweenanameandalambda-expression:

valsquare=lam(x:int):int=>x*x

Asanotherexample,pleasenotethatthetwooccurrencesofthesymbol fact inthefollowingcoderefertotwodistinctfunctions:

fn

fact(x:int):int=

ifx>0thenx*fact(x-1)else1

(*endof[fact]*)

Whilethefirst fact (totheleftoftheequalitysymbol)referstothe(non-recursive)functionbeing

Page 39: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

defined,thesecondoneissupposedtohavebeendeclaredpreviously.

A recursive function can also be defined as a recursive value. For instance, the recursive functionfact definedabovecanbedefinedasfollows:

val

rec

fact:int->int=

lam(x)=>

ifx>0thenx*fact(x-1)else1

(*endof[fact]*)

wherethekeyword rec indicatesthat fact isdefinedrecursively,thatis,itisallowedtoappearinitsowndefinition.Infact, theformerdefinitionof fact isdirectly translated into the latteronebythecompiler.Ofcourse,onemayalsouseareferencetoimplementrecursion:

val

fact=ref<int->int>($UNSAFE.cast(0))

val()=

!fact:=

(

lam(x:int):int=>ifx>0thenx*!fact(x-1)else1

)(*endof[val]*)

But this isdefinitelynot a style Iwould like toadvocate.For the sakeof completion, Ipresentyetanotherwaytodefine fact asafixed-pointexpression:

val

fact=

fixf(x:int):int=>

ifx>0thenx*f(x-1)else1

(*endof[fact]*)

Of course, if one wants to, then one can always replace a lambda-expression with a fixed-pointexpression(orsimplyfix-expressionforshort).Forinstance, lambda(x:int):int=>x+x canbewrittenas fix_(x:int):int=>x+x .

For defining mutually recursive functions, one can simply use the keyword and to concatenatefunctiondefinitions.Forinstance,thefollowingcodedefinestwofunctions isevn and isodd mutuallyrecursively:

fun

Page 40: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

isevn(x:int):bool=

ifx>0thenisodd(x-1)elsetrue

and

isodd(x:int):bool=

ifx>0thenisevn(x-1)elsefalse

The code, as one may have guessed, is translated by the compiler into the following form (fordefiningtwomutuallyrecursivevalues):

val

rec

isevn:int->bool=

lam(x)=>ifx>0thenisodd(x-1)elsetrue

and

isodd:int->bool=

lam(x)=>ifx>0thenisevn(x-1)elsefalse

One can certainly use the keyword and to concatenate definitions of non-recursive functions, butdoingsoisprobablyjustacuriosity(insteadofameaningfulpractice).

Even at this point, I have not presented all of the possible ways to define functions in ATS. Forinstance,onecanalsodefinestack-allocatedclosure-functionsinATS,whichmaybeeitherrecursiveornon-recursive.Iplantointroducesuchfunctionselsewhereinthistutorial.

Often, the interface (that is, type) for a function is declared at one place and its definition (orimplementation) is given at another place. For instance, one may first introduce the followingdeclaration:

externfunfact(x:int):int

Later,onecanimplement fact accordingtotheabovedeclaration:

implement

fact(x)=

ifx>0thenx*fact(x-1)else1

//endof[fact]

When implement is used to initiate the definition of a function, any previously declared symbols(includingtheonethatisbeingdefined)canappearinthedefinition.Ifitisdesirable,onemayreplaceimplement with implmnt .

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 41: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 42: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 43: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter10.DatatypesDatatypesareaformofuser-definedtypesforclassifyingdata(orvalues).ThesupportfordatatypesandpatternmatchinginATSisprimarilyadoptedfromML.

Thefollowingcodedeclaresadatatypeofthename weekday forvaluesrepresentingweekdays:

datatypeweekday=

|Monday|Tuesday|Wednesday|Thursday|Friday

There are five data constructors associated with weekday , which are Monday , Tuesday , Wednesday ,Thursday , and Friday .All of these data constructors are nullary, that is, they take no arguments toformvalues(ofthetype weekday ).

Eachnullaryconstructorisrepresentedasasmallinteger(e.g.,onethatislessthan1024).Onecanusethefollowingfunction weekday2int tofindouttheintegersreprsentingtheconstructorsassociatedwith weekday :

//

staloadUN="prelude/SATS/unsafe.sats"

//

fun

weekday2int

(wd:weekday):int=$UN.cast{int}($UN.cast{intptr}(wd))

//

Thesmallintegerrepresentinganullaryconstructorisoftenreferredtoasthetagoftheconstructor.In this case, the tags for Monday , Tuesday , Wednesday , Thursday , and Friday are 0, 1, 2, 3, and 4,respectively.

Givenanullaryconstructor foo ,both foo and foo() canbeused to refer thevalueconstructedbyfoo . However, only foo() can be used as the pattern that matches this value. For instance, thefollowing function testswhether a given value of the type weekday is formedwith the constructorFriday :

fun

isFriday(x:weekday):bool=

case+xofFriday()=>true|_=>false

Page 44: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Notethatthepattern Friday() cannotbereplacedwith Friday asthelatteristreatedasavariablewhenusedasapattern.Ontheotherhand,bothofthefollowingassertionsholdatrun-timeas Friday andFriday() refertothesamevalue:

val()=assertloc(isFriday(Friday))

val()=assertloc(isFriday(Friday()))

If thereisonlyoneconstructorassociatedwithadatatype, thenthereisnotagintherepresentationforvaluesofthisdatatype.

Adatatypeislist-likeiftherearetwodataconstructorsassociatedwithitsuchthatoneisnullary(nil-like)andtheotherisnon-nullary(cons-like).Forinstance,thedatatype ab declaredasfollowsislist-like:

datatypeab=Aof()|Bof(bool)

Thevaluesofalist-likedatatypearerepresentedinaspecialway.Givenavalueofthedatatype;ifitisconstructedwiththenil-likeconstructor,thenitisrepresentedasthenull-pointer;ifitisconstructedwith the cons-like constructor, then it is reprenstend as a heap-allocated tuple containing all of theargumentspassedtotheconstructor.Intheabovecase,thevalue A() isrepresentedasthenullpointer,andthevalue B(b) foreachboolean b isrepresentedasaheap-allocatedsingletontuplecontainingtheonlycomponent b .Thisdescriptioncanbereadilyverifiedwiththefollowingcode:

val()=assertloc(iseqz($UN.cast{ptr}(A())))

val()=assertloc(true=$UN.ptr0_get<bool>($UN.cast{ptr}(B(true))))

val()=assertloc(false=$UN.ptr0_get<bool>($UN.cast{ptr}(B(false))))

Thefollowingdeclarationintroducesadatatypeofthename abc :

datatypeabc=

|Aof()|Bof(bool)|Cof(int,double)

The three constructors associated with abc are A , B , and C ; A is nullary; B is unary, taking aboolean to form a value (of the type abc ); C is binary, taking an integer and a float (of doubleprecision)toformavalue(ofthetype abc ).

Inageneralcase,ifadataconstructorisn-aryforsomepositiven,theneachvalueitconstructsisaheap-allocatedtupleofn+1components,wherethefirstoneisthetagassignedtotheconstructorandtherestaretheargumentspassedtotheconstructor.Forinstance,thefollowingfunctioncanbecalled

Page 45: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

tofindoutthetagsassignedtotheconstructorsassociatedwith abc :

fun

abc2tag

(x:abc):int=let

valp=$UN.cast{intptr}(x)

in

//

case+0of

|_whenp<1024=>$UN.cast{int}(p)

|_(*heap-allocated*)=>$UN.ptr0_get<int>($UN.cast{ptr}(p))

//

end//endof[abc2tag]

Inthiscase,thetagsassignedto A , B ,and C are0,1,and2,respectively.

Datatypes can be defined recursively. As an example, the following declaration introduces arecursivelydefineddatatype intexp (forrepresentingarithemeticintegerexpressions):

datatype

intexp=

|Intofint

|Negof(intexp)

|Addof(intexp,intexp)

|Subof(intexp,intexp)

Forinstance, (1+2)-3 canberepresentedas Sub(Add(Int(1),Int(2)),Int(3)) .Asanotherexample,thefollowing code introduces two mutually recursively defined datatypes intexp and boolexp (forintegerexpressionsandbooleanexpressions,respectively):

datatype

intexp=

|Intofint

|Negof(intexp)

|Addof(intexp,intexp)

|Subof(intexp,intexp)

|IfThenElseof(boolexp,intexp,intexp)

and

boolexp=

|Boolofbool//constant

|Notof(boolexp)//negation

|Lessof(intexp,intexp)//Less(x,y):x<y

|LessEqof(intexp,intexp)//LessEq(x,y):x<=y

Page 46: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

|Conjof(boolexp,boolexp)//Conj(x,y):x/\y

|Disjof(boolexp,boolexp)//Disj(x,y):x\/y

The code below implements two mutually recursive functions eval_intexp and eval_boolexp forevaluatingintegerexpressionsandbooleanexpressions,respectively:

//

symintreval

//

extern

funeval_intexp:intexp->int

extern

funeval_boolexp:boolexp->bool

//

overloadevalwitheval_intexp

overloadevalwitheval_boolexp

//

(**************)

//

implement

eval_intexp

(e0)=(

//

case+e0of

|Int(i)=>i

|Neg(e)=>~eval(e)

|Add(e1,e2)=>eval(e1)+eval(e2)

|Sub(e1,e2)=>eval(e1)-eval(e2)

|IfThenElse

(e_test,e_then,e_else)=>

ifeval(e_test)theneval(e_then)elseeval(e_else)

//

)(*endof[eval_intexp]*)

//

implement

eval_boolexp

(e0)=(

//

case+e0of

|Bool(b)=>b

|Not(e)=>~eval(e)

|Less(e1,e2)=>eval(e1)<eval(e2)

|LessEq(e1,e2)=>eval(e1)<=eval(e2)

|Conj(e1,e2)=>eval(e1)&&eval(e2)

|Disj(e1,e2)=>eval(e1)||eval(e2)

//

Page 47: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

)(*endof[eval_boolexp]*)

//

(**************)

Thedatatypespresentedinthischapteraresimpledatatypes.Othermoreadvancedformsofdatatypesinclude polymorphic datatypes, dependent datatypes, and linear datatypes, which will be coveredelsewhere.

Pleasefindon-linetheentiretyofthecodeusedinthischapterplussomecodefortesting.

Page 48: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 49: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 50: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter11.FunctionalListsA functional list is just a singly-linked list that is immutable after its construction. The followingdatatypedeclarationintroducesatype list forfunctionallists:

//

datatype

list(a:t@ype,int)=

|list_nil(a,0)of()

|{n:nat}

list_cons(a,n+1)of(a,list(a,n))

//

GivenatypeTandanintegerN,thetype list(T,N) isforalistoflengthNthatcontainselementsoftype T. The interfaces for various functions on functional lists can be found in the SATS fileprelude/SATS/list.sats,whichisautomaticallyloadedbyatsopt.

There are various functions in ATSLIB for list construction. In practice, a list is usually built bymakingdirectuseof theconstructors list_nil and list_cons . For instance, the following functionfromto buildsalistofintegersbetweentwogivenones:

//

fun

fromto

{m,n:int|m<=n}

(

m:int(m),n:int(n)

):list(int,n-m)=

ifm<nthenlist_cons(m,fromto(m+1,n))elselist_nil()

//

Traversingalistiscommonlydonebymakinguseofpatternmatching.Forinstance,thefollowingcodeimplementsafunctionforcomputingthelengthofagivenlist:

//

fun

{a:t@ype}

list_length

{n:nat}

(

xs:list(a,n)

):int(n)=let

Page 51: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

//

fun

loop

{i,j:nat}

(

xs:list(a,i),j:int(j)

):int(i+j)=

(

case+xsof

|list_nil()=>j

|list_cons(_,xs)=>loop(xs,j+1)

)

//

in

loop(xs,0)

end//endof[list_length]

//

Given a non-empty list xs, xs.head() and xs.tail() refer to the head and tail of xs, respectively,where .head() and .tail() areoverloadeddot-symbols.Forinstance,thefunction list_foldleft forfoldingagivenlistfromtheleftcanbeimplementedasfollows:

//

fun

{a,b:t@ype}

list_foldleft

{n:nat}

(

f:(a,b)->a,ini:a,xs:list(b,n)

):a=

ifiseqz(xs)

theninielselist_foldleft(f,f(ini,xs.head()),xs.tail())

//endof[if]

//

And the function list_foldright for folding a given list from the right can be implemented asfollows:

//

fun

{a,b:t@ype}

list_foldright

{n:nat}

(

f:(a,b)->b,xs:list(a,n),snk:b

Page 52: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

):b=

ifiseqz(xs)

thensnkelsef(xs.head(),list_foldright(f,xs.tail(),snk))

//endof[if]

//

Notethat list_foldleft istail-recursivebut list_foldright isnot.

Asanapplicationof list_foldleft , thefollowingcodeimplementsafunctionforreversingagivenlist:

fun

{a:t@ype}

list_reverse

(

xs:List0(a)

):List0(a)=

(

list_foldleft<List0(a),a>

(lam(xs,x)=>list_cons(x,xs),list_nil,xs)

)

wherethetypeconstructor List0 isforlistsofunspecifiedlength:

typedefList0(a:t@ype)=[n:nat]list(a,n)

Clearly, list_reverse is length-preserving, that is, it always returns a list of the same length as itsinput.Unfortunately,thisinvariantisnotcapturedintheaboveimplementationof list_reverse basedon list_foldleft .Forthepurposeofcomparison,anotherimplementationof list_reverse isgivenasfollowsthatcapturestheinvariantof list_reverse beinglength-preserving:

fun

{a:t@ype}

list_reverse

{n:nat}

(

xs:list(a,n)

):list(a,n)=let

//

fun

loop{i,j:nat}

(

xs:list(a,i),ys:list(a,j)

):list(a,i+j)=

Page 53: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

case+xsof

|list_nil()=>ys

|list_cons(x,xs)=>loop(xs,list_cons(x,ys))

//

in

loop(xs,list_nil)

end//endof[list_reverse]

Asanapplicationof list_foldright ,thefollowingcodeimplementsafunctionforconcatenatingtwogivenlists:

//

fun

{a:t@ype}

list_append

(

xs:List0(a),ys:List0(a)

):List0(a)=

list_foldright<a,List0(a)>(lam(x,xs)=>list_cons(x,xs),ys,xs)

//

Thetypeassignedto list_append statesthatthisfunctiontakestwolistsasitsargumentsandreturnsoneofunspecifiedlength.Forthepurposeofcomparison,anotherimplementationof list_append isgivenasfollows:

//

fun

{a:t@ype}

list_append

{m,n:nat}

(

xs:list(a,m),ys:list(a,n)

):list(a,m+n)=

(

case+xsof

|list_nil()=>ys

|list_cons(x,xs)=>list_cons(x,list_append(xs,ys))

)

//

where the type assigned to list_append states that this function takes two lists of length m and n,respectively,andreturnsanotherlistoflengthm+n.

Onemaythinkofafunctional listasarepresentationfor thefinitemappingthatmapseachnatural

Page 54: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

numberilessthanthelengthofthelisttoelementiinthelist.Thefollowingfunction list_get_at isforaccessingalistelementatagivenposition:

//

fun

{a:t@ype}

list_get_at

{n:nat}

(

xs:list(a,n),i:natLt(n)

):a=

ifi>0thenlist_get_at(xs.tail(),i-1)elsexs.head()

//

This function can be called through the use of the bracket notation. In other words, xs[i] isautomatically interpreted as list_get_at(xs, i) whenever xs and i are a list and an integer,respectively. Note that the time-complexity of list_get_at(xs, i) is O(i). If one uses list_get_at

frequentlywhenhandlinglists,thenitisalmostalwaysasuresignofpoorprogrammingstyle.

There is no destructive update on a functional list as it is immutable. The following functionlist_set_at canbecalledtoconstructalistthatdiffersfromagivenoneonlyatagivenposition:

//

fun

{a:t@ype}

list_set_at

{n:nat}

(

xs:list(a,n),i:natLt(n),x0:a

):list(a,n)=

ifi>0

thenlist_cons(xs.head(),list_set_at(xs.tail(),i-1,x0))

elselist_cons(x0,xs.tail())

//endof[if]

//

Whileitisfinetocall list_set_at occasionally,aneedtodosorepeatedlyoftenindicatesthatanotherdatastructureshouldprobablybechoseninplaceoffunctionallist.

Functionallistsarebyfarthemostwidelyuseddatastructureinfunctionalprogramming.However,oneshouldnotattempttouseafunctionallistlikeanarrayasdoingsoisinefficientbothtime-wiseandmemory-wise.

Page 55: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Pleasefindon-linetheentiretyofthecodeusedinthischapterplussometestingcode.

Page 56: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 57: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 58: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter12.FunctionalSetsandMapsBoth(finite)setsand(finite)mapsarecommonlyuseddatastructures.Functionalsetsandmapsareimmutableaftertheirconstruction.Insertionintoorremovalfromafunctionalset/mapresultsintheconstructionofanewset/mapwhiletheoriginaliskeptintact.Usuallythenewlyconstructedset/mapandtheoriginalonesharealotofunderlyingrepresentation.Notethatafunctionalset/mapcannotbesafely freed explicitly and thememory for representing it can only be reclaimed throughgarbagecollection(GC).

Page 59: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

FunctionalSets

Supposethatasetisneededforcollectingvaluesoftype elt_t .Thefollowingcodeessentiallysetsupaninterfaceforcreatingandoperatingonsuchasetbasedonabalanced-treeimplementationinATSLIB/libats:

local

//

typedefelt=elt_t

//

staload

FS="libats/ML/SATS/funset.sats"

implement

$FS.compare_elt_elt<elt>(x,y)=compare(x,y)

//

in(*in-of-local*)

#include"libats/ML/HATS/myfunset.hats"

end//endof[local]

Pleasefindon-linetheHATSfilementionedinthecode,whichisjustaconveniencewrappermadetosimplifyprogrammingwith functional sets.Note that it is assumedhere that there is a comparisonfunctiononvaluesof the type elt_t thatoverloads the symbol compare . If this is not the case, oneneedstoimplementsuchafunction.

Assumethat elt_t is int .Thefollowinglineofcodecreatesafunctionalset(ofintegers)containingnoelements:

valmyset=myfunset_nil()

Thefunctionforinsertinganelementintoagivensetisassignedthefollowingtype:

//

funmyfunset_insert(xs:&myset>>_,x0:elt):bool

//

Thedot-symbol .insert isoverloadedwiththefunction myfunset_insert .Notethatthefirstargumentof myfunset_insert is call-by-reference. If the given element is inserted into the given set, then thenewlycreatedsetisstoredintothecall-by-referenceargumentand false isreturned(toindicatenoerror).Otherwise, true isreturned(toindicateafailure).Thefollowingfewlinesofcodeshowshow

Page 60: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

insertioncanbeoperatedonafunctionalset:

//

varmyset=myset

//

val-false=myset.insert(0)//inserted

val-(true)=myset.insert(0)//notactuallyinserted

val-false=myset.insert(1)//inserted

val-(true)=myset.insert(1)//notactuallyinserted

//

The first line in theabovecodemayseempuzzling: Its solepurpose is tocreatea left-value tobepassed as the first argument to myfunset_insert .During the course of debugging, onemaywant toprintoutthevaluescontainedinagivenset:

//

val()=fprintln!(stdout_ref,"myset=",myset)

//

where the symbol fprint is overloadedwith fprint_myset . The function for removing an elementfromagivensetisassignedthefollowingtype:

//

funmyfunset_remove(xs:&myset>>_,x0:elt):bool

//

Thedot-symbol .remove isoverloadedwiththefunction myfunset_remove .Notethatthefirstargumentof myfunset_remove iscall-by-reference.Ifthegivenelementisremovedfromthegivenset,thenthenewlycreatedsetisstoredintothecall-by-referenceargumentand true isreturned.Otherwise, falseisreturned.Thefollowingfewlinesofcodeshowshowremovalcanbeoperatedonafunctionalset:

val-true=myset.remove(0)//removed

val-false=myset.remove(0)//notactuallyremoved

val-true=myset.remove(1)//removed

val-false=myset.remove(1)//notactuallyremoved

Various common set operations can be found in libats/ML/HATS/myfunset.hats.By following thetypes assigned to these operations, one should have no difficulty in figuring out how they aresupposedtobecalled.Pleasefindtheentiretyofthecodeusedinthissectionon-line.

Page 61: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

FunctionalMaps

Supposethatamapisneededformappingkeysoftype key_t toitemsoftype itm_t .Thefollowingcodeessentiallysetsupaninterfaceforcreatingandoperatingonsuchamapbasedonabalanced-treeimplementationinATSLIB/libats:

local

//

typedef

key=key_tanditm=itm_t

//

staload

FM="libats/ML/SATS/funmap.sats"

implement

$FM.compare_key_key<key>(x,y)=compare(x,y)

//

in(*in-of-local*)

#include"libats/ML/HATS/myfunmap.hats"

end//endof[local]

Pleasefindon-linetheHATSfilementionedinthecode,whichisjustaconveniencewrappermadetosimplifyprogrammingwithfunctionalmaps.Notethatitisassumedherethatthereisacomparisonfunctiononvaluesof the type key_t thatoverloads the symbol compare . If this is not the case, oneneedstoimplementsuchafunction.

Assumethat key_t is string and itm_t is int .Thefollowinglineofcodecreatesanemptyfunctionalmap:

valmymap=myfunmap_nil()

Thefollowingfewlinesinsertsomekey/itempairsinto mymap :

//

varmymap=mymap

//

val-~None_vt()=mymap.insert("a",0)

val-~Some_vt(0)=mymap.insert("a",1)

//

val-~None_vt()=mymap.insert("b",1)

val-~Some_vt(1)=mymap.insert("b",2)

//

Page 62: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

val-~None_vt()=mymap.insert("c",2)

val-~Some_vt(2)=mymap.insert("c",3)

//

Thedot-symbol .insert isoverloadedwithafunctionofthename myfunmap_insert .Thefirstlineintheabovecodemayseempuzzling:Itssolepurposeistocreatealeft-valuetobepassedasthefirstargument to myfunmap_insert . Given a key and an item, mymap.insert inserts the key/item pair intomymap .Ifthekeyisinthedomainofthemaprepresentedby mymap beforeinsertion,thentheoriginalitemassociatedwiththekeyisreturned.Otherwise,noitemisreturned.Ascanbeexpected,thesizeof mymap is3atthispoint:

val()=assertloc(mymap.size()=3)

Thedot-symbol .size is overloadedwith a function of the name myfunmap_size , which returns thenumberofkey/itempairsstoredinagivenmap.Duringthecourseofdebugging,onemaywanttoprintoutthekey/itempairsinagivenmap:

//

val()=fprintln!(stdout_ref,"mymap=",mymap)

//

where the symbol fprint is overloadedwith fprint_mymap . The next two lines of code show howsearchwithagivenkeyoperatesonamap:

val-~None_vt()=mymap.search("")

val-~Some_vt(1)=mymap.search("a")

Thedot-symbol .search isoverloadedwithafunctionofthename myfunmap_search ,whichreturnstheitemassociatedwithagivenkeyifitisfound.Thenextfewlinesofcoderemovesomekey/itempairsfrom mymap :

//

val-true=mymap.remove("a")

val-false=mymap.remove("a")

//

val-~Some_vt(2)=mymap.takeout("b")

val-~Some_vt(3)=mymap.takeout("c")

//

Thedot-symbol .remove isoverloadedwitha functionof thename myfunmap_remove for removingakey/itempairofagivenkey.Ifakey/itempairisremoved,thenthefunctionreturnstrue.Otherwise,

Page 63: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

itreturnsfalsetoindicatesthatnokey/itempairofthegivenkeyisstoredinthemapbeingoperatedon.Thedot-symbol .takeout is overloadedwith a functionof thename myfunmap_takeout , which issimilarto myfunmap_remove exceptingforreturningtheremoveditem.

Variouscommonmapoperationscanbefoundinlibats/ML/HATS/myfunmap.hats.Byfollowingthetypes assigned to these operations, one should have no difficulty in figuring out how they aresupposedtobecalled.Pleasefindtheentiretyofthecodeusedinthissectionon-line.

Page 64: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 65: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 66: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter13.ExceptionsWhile exceptions can be very useful in practice, it is also very common to see code thatmisusesexceptions.

Generallyspeaking,thereareexceptionsthataremeanttoberaisedbutnotcapturedforthepurposeofabortingprogramexecution,andtherearealsoexceptions(oftendeclaredlocally)thataremeantto be raised and then captured so as to change the flow of program execution. For instance, theexception ArraySubscriptExn is raisedwhenout-of-boundsarraysubscripting isdetectedat run-time.Once it is raised, ArraySubscriptExn is usually not meant to be captured. While there is certainlynothingpreventingaprogramerfromwritingcodethatcapturesaraised ArraySubscriptExn ,amajorconcern is that reasoning can become greatly complicated on code that does so. In the followingpresentation,Iwillsoleyfocusonexceptionsthataremeanttoberaisedandthencaptured.

Let usnow take a look at the following code that implements a function for finding the rightmostelementinalistthatsatisfiesagivenpredicate:

extern

fun{a:t@ype}

list_find_rightmost

(List(a),(a)-<cloref1>bool):Option_vt(a)

//

implement{a}

list_find_rightmost

(xs,pred)=let

//

funaux

(

xs:List(a)

):Option_vt(a)=

case+xsof

|nil()=>None_vt()

|cons(x,xs)=>let

valres=aux(xs)

in

case+resof

|Some_vt_=>res

|~None_vt()=>

ifpred(x)thenSome_vt(x)elseNone_vt()

//endof[None]

end(*endof[cons]*)

//

Page 67: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

in

aux(xs)

end//endof[list_find_rightmost]

Supposethat list_find_rightmost iscalledonalistxsoflengthN(forsomelargenaturalnumberN)andapredicatepred.Theevaluationofthiscallleadstoacalltotheinnerfunction aux ,whichinturngeneratesN additional recursive calls to aux .Assume that only the last element of xs satisfies thepredicate pred. Then there are still N-1 call frames for aux on the call stack when the rightmostelement satisfying the given predicate is found, and these frames need to be unwindedone-by-onebefore the found element can be returned to the original call to list_find_rightmost . This form ofinefficiencyiseliminatedinthefollowingexception-basedimplementationof list_find_rightmost :

implement{a}

list_find_rightmost

(xs,pred)=let

//

exceptionFoundof(a)

//

funaux

(

xs:List(a)

):void=

case+xsof

|nil()=>()

|cons(x,xs)=>let

val()=aux(xs)

in

ifpred(x)then$raiseFound(x)else()

end(*endof[cons]*)

//

in

//

trylet

val()=aux(xs)

in

None_vt()

endwith

|~Found(x)=>Some_vt(x)

//

end//endof[list_find_rightmost]

Whenatry-with-expressionisevaluated,alabeliscreatedfortheportionofthecallstackneededtoevaluate theclauses (oftenreferred toasexception-handlers) following thekeyword with , and this

Page 68: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

label is thenpushedonto adesignatedglobal stack.When an exception is raised, the labels on theglobalstackaretriedone-by-oneuntiltheraisedexceptioniscapturedbyanexception-handler(thatis, the value representing the exceptionmatches the pattern guard of the exception-handler) or thecurrentprogramevaluationaborts.Theaboveexception-basedimplementationof list_find_rightmostusesaraisedexceptiontocarrytheelementfoundduringarecursivecallto aux sothatthiselementcan be returned in a single jump to the original call to list_find_rightmost , bypassing all theintermediatecallframes(forrecursivecallsto aux )onthecallstack.Ingeneral,therangebetweenthe pointwhere an exception is raised and the pointwhere the raised exception is captured shouldspanmultiplecallframes.Ifnot,thentheuseofexceptionmaybequestionable.

Theimplementationoftherun-timesupportforexceptionsinATSmakesuseofthefunction allocadeclaredinalloca.handthefunctions setjmp and longjmp declaredinsetjmp.h.Ifgccorclang is

usedtocompiletheCcodegeneratedfromATSsource,onecanpasstheflag-D_GNU_SOURCEsoastomakesurethattheheaderfilealloca.hisproperlyincluded.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 69: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 70: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 71: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter14.ReferencesAreferenceisasingletonarray,thatis,anarrayofsize1.Itispersistentinthesensethatthe(heap-allocated)memory for storing the content of a reference cannot be freedmanually in a type-safemanner.Instead,itcanonlybereclaimedthroughgarbagecollection(GC).

GivenaviewtypeVT,thetypeforreferencestovaluesofviewtypeVTis ref (VT).Forconvenience,thetypeconstructor ref isdeclaredtobeabstractinATS.However,itcanbedefinedasfollows:

typedefref(a:vt@ype)=[l:addr](vbox(a@l)|ptrl)

Theinterfacesforvariousfunctionsonreferencescanbefoundinprelude/SATS/reference.sats.

Forcreatingareference,thefunctiontemplate ref_make_elt ofthefollowinginterfacecanbecalled:

fun{a:vt@ype}ref_make_elt(x:a):<!wrt>refa

Itisalsoallowedtousetheshorthand ref for ref_make_elt .Notethatthesymbol !wrt indicatesthattheso-called wrt -effectmayoccurwhen ref_make_elt iscalled.

Forreadingfromandwritingthroughareference,thefunctiontemplates ref_get_elt and ref_set_eltcanbeused,respectively,whichareassignedthefollowingtypes:

fun{a:t@ype}ref_get_elt(r:refa):<!ref>a

fun{a:t@ype}ref_set_elt(r:refa,x:a):<!refwrt>void

Note that the symbol !ref indicates that the so-called ref-effect may occur when ref_get_elt isevaluated.Similarly, !refwrt meansbothref-effectandwrt-effectmayoccurwhen ref_set_elt .Givenareference r andavalue v , ref_get_elt(r) and ref_set_elt(r,v) canbewrittenas !r and !r:=v ,respectively,andcanalsobewrittenas r[] and r[]:=v ,respectively,intermsofbracket-notation.

Areferenceistypicallyemployedtorecordsomeformofpersistentstate.Forinstance,followingissuchanexample:

local

//

#defineBUFSZ128

//

valcount=ref<int>(0)

//

Page 72: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

in(*inof[local]*)

fungenNewName

(prfx:string):string=let

valn=!count

val()=!count:=n+1

varres=@[byte][BUFSZ]((*void*))

valerr=

$extfcall(

int,"snprintf",addr@res,BUFSZ,"%s%i",prfx,n

)(*endof[$extfcall]*)

in

strptr2string(string0_copy($UNSAFE.cast{string}(addr@res)))

end//endof[genNewName]

end//endof[local]

The function genNewName is called to generate fresh names.As the integer content of the referencecount is updated whenever a call to genNewName is made, each name returned by genNewName isguaranteedtohavenotbeengeneratedbefore.Notethat theuseof $extfcall isformakingadirectcalltothefunction snprintf inC.

MisuseofReferencesReferencesarecommonlymisusedinpractice.Thefollowingprogramisoftenwritten by a beginner of functional programming who has already learned (some) imperativeprogramming:

funfact

(n:int):int=let

valres=ref<int>(1)

funloop(n:int):<cloref1>void=

ifn>0then(!res:=n*!res;loop(n-1))else()

val()=loop(n)

in

!res

end//endof[fact]

Thefunction fact iswritteninsuchastyleassomewhatadirecttranslationofthefollowingCcode:

intfact(intn){

intres=1;

while(n>0){res=n*res;n=n-1;};

returnres;

}

Page 73: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

In the ATS implementation of fact , res is a heap-allocated reference and it becomes garbage(waitingtobereclaimedbytheGC)afteracallto fact returns.Ontheotherhand,thevariable res intheCimplementationof fact isstack-allocated(oritcanevenbemappedtoamachineregister),andthere is no generated garbage after a call to fact returns. A proper translation of the CimplementationinATScanactuallybegivenasfollows:

funfact

(n:int):int=let

funloop(n:int,res:int):int=

ifn>0thenloop(n-1,n*res)elseres

//endof[loop]

in

loop(n,1)

end//endof[fact]

whichmakesnouseofreferencesatall.

Unlessstrongjustificationcanbegiven,makingextensiveuseof(dynamicallycreated)referencesisoftenasuresignofpoorcodingstyle.

Statically Allocated References Creating a reference by calling ref_make_elt involves dynamicmemoryallocation.Ifthisisnotdesirableorevenacceptable,itispossibletoonlyemploystaticallyallocatedmemoryinareferencecreationasisshownbelow:

varmyvar:int=0

valmyref=ref_make_viewptr(view@(myvar)|addr@(myvar))

Thefunction ref_make_viewptr takesapointerandaproofofsomeat-viewassociatedwiththepointerandreturnsareferenceafterconsumingtheproof.As ref_make_viewptr isacast-function,itcausesnorun-timeoverhead.Intheabovecode, myvar isstaticallyallocatedanditisnolongeravailableafteritsat-viewproofisconsumedby ref_make_viewptr .Itshouldbeinterestingtoobservethatboth myvarand myref are just the same pointer in C but they are the reification of fundamentally differentconceptsinATS:theformerisalinearvariablewhilethelatterisanon-linearreference.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 74: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 75: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 76: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter15.PersistentArraysApersistentarrayofsizenisjustnheap-allocatedcells(orreferences)inarow.Itispersistentinthesensethatthememoryallocatedforthearraycannotbefreedmanually.Instead,itcanonlybesafelyreclaimedthroughgarbagecollection(GC).

Given a viewtype VT, the type for persistent arrays containing N values of viewtype VT isarrayref(VT, N) .Note that arrays inATS are the same as those inC:There is no size informationattachedtothem.TheinterfacesforvariousfunctionsonpersistentarrayscanbefoundintheSATSfileprelude/SATS/arrayref.sats,whichisautomaticallyloadedbyatsopt.

There are various functions in ATSLIB for array creation. For instance, the following two arecommonlyused:

fun{a:t@ype}

arrayref_make_elt

{n:nat}(asz:size_tn,elt:a):<!wrt>arrayref(a,n)

//endof[arrayref_make_elt]

fun{a:t@ype}

arrayref_make_listlen

{n:int}(xs:list(a,n),n:intn):<!wrt>arrayref(a,n)

//endof[arrayref_make_listlen]

Appliedtoasizeandanelement, arrayref_make_elt returnsanarrayofthegivensizeinwhicheachcell is initialized with the given element. Applied to a list of elements and the length of the list,arrayref_make_listlen returnsanarrayofsizeequaltothegivenlengthinwhicheachcellisinitializedwiththecorrespondingelementinthegivenlist.

Forreadingfromandwritingtoanarray,thefunctiontemplates arrayref_get_at and arrayref_set_atcanbeused,respectively,whichareassignedthefollowinginterfaces:

fun{a:t@ype}

arrayref_get_at

{n:int}(A:arrayref(a,n),i:sizeLt(n)):<!ref>a

fun{a:t@ype}

arrayref_set_at

{n:int}(A:arrayref(a,n),i:sizeLt(n),x:a):<!ref>void

Page 77: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Givenanarray A ,anindex i andavalue v , arrayref_get_at(A,i) and arrayref_set_at(A,i,v) canbewrittenas A[i] and A[i]:=v ,respectively.

Asanexample,thefollowingfunctiontemplatereversesthecontentofagivenarray:

fun{a:t@ype}

arrayref_reverse{n:nat}

(

A:arrayref(a,n),n:size_t(n)

):void=let

//

funloop

{i:nat|i<=n}.<n-i>.

(

A:arrayref(a,n),n:size_tn,i:size_ti

):void=let

valn2=half(n)

in

ifi<n2thenlet

valtmp=A[i]

valni=pred(n)-i

in

A[i]:=A[ni];A[ni]:=tmp;loop(A,n,succ(i))

endelse()//endof[if]

end//endof[loop]

//

in

loop(A,n,i2sz(0))

end//endof[arrayref_reverse]

Ifthetest i<n2 ischangedto i<=n2 ,atype-erroristobereported.Why?Thereasonisthat A[n-1-i] becomesout-of-boundsarraysubscriptinginthecasewhere n and i bothequalzero.Giventhatitis very unlikely to encounter a case where an array of size 0 is involved, a bug like this, if notdetectedearly,canbeburiedsoscarilydeep!

Thecarefulreadermayhavealreadynoticedthatthesort t@ype isassignedtothetemplateparametera . In other words, the above implementation of arrayref_reverse cannot handle a case where thevaluesstoredinagivenarrayareofsomelineartype.Thereasonforchoosingthesort t@ype isthatboth arrayref_get_at and arrayref_set_at can only be applied to an array containing values of anonlinear type. In thefollowingimplementation, the templateparameter isgiven thesort vt@ype sothatanarraycontaininglinearvalues,thatis,valuesofsomelineartypecanbehandled:

Page 78: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

fun{a:vt@ype}

arrayref_reverse{n:nat}

(

A:arrayref(a,n),n:size_t(n)

):void=let

//

funloop

{i:nat|i<=n}.<n-i>.

(

A:arrayref(a,n),n:size_tn,i:size_ti

):void=let

valn2=half(n)

in

ifi<n2thenlet

val()=arrayref_interchange(A,i,pred(n)-i)inloop(A,n,succ(i))

endelse()//endof[if]

end//endof[loop]

//

in

loop(A,n,i2sz(0))

end//endof[arrayref_reverse]

Theinterfaceforthefunctiontemplate arrayref_interchange isgivenbelow:

fun{a:vt@ype}

arrayref_interchange{n:int}

(A:arrayref(a,n),i:sizeLtn,j:sizeLtn):<!ref>void

//endof[arrayref_interchange]

Note that arrayref_interchange can not be implemented in terms of arrayref_get_at andarrayref_set_at (unlesssomeformoftype-unsafecodeisemployed).

Therearevariousfunctionsavailablefortraversinganarrayfromlefttorightorfromrighttoleft.Also,thefollowingtwofunctionscanbeconvenientlycalledtotraverseanarrayfromlefttoright:

//

fun{a:t0p}

arrayref_head{n:pos}(A:arrayref(a,n)):(a)//A[0]

fun{a:t0p}

arrayref_tail{n:pos}(A:arrayref(a,n)):arrayref(a,n-1)

//

overload.headwitharrayref_head

overload.tailwitharrayref_tail

//

Page 79: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Forinstance,thefold-leftfunctionforarrayscanbeimplementedasfollows:

fun{a,b:t@ype}

arrayref_foldleft{n:int}

(

f:(a,b)->a,x:a,A:arrayref(b,n),n:size_t(n)

):a=

(

ifn>0

thenarrayref_foldleft<a,b>(f,f(x,A.head()),A.tail(),pred(n))

elsex

//endof[if]

)(*endof[arrayref_foldleft]*)

Ascanbeexpected, A.head and A.tail translateinto A[0] and ptr_succ<T>(p0) ,respectively,whereTisthetypefortheelementsstoredinAandp0isthestartingaddressofA.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 80: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 81: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 82: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter16.PersistentArrays-with-sizeIusethenamearray-with-size to refer toapersistentarraywithattachedsize information.GivenaviewtypeVT,thetypeforanarray-with-sizethatcontainsNvaluesofviewtypeVTis arrszref(VT,N) .Essentially,suchavalueisaboxedpairoftwocomponentsoftypes arrayref(VT,N) and size_t(N) .The interfaces for various functions on persistent arrays-with-size can be found inprelude/SATS/arrayref.sats.

For creating an array-with-size, the following functions arrszref_make_arrpsz andarrszref_make_arrayref canbecalled:

fun{}

arrszref_make_arrpsz

{a:vt0p}{n:int}(arrpsz(INV(a),n)):arrszref(a)

fun{}

arrszref_make_arrayref

{a:vt0p}{n:int}(arrayref(a,n),size_t(n)):arrszref(a)

//endof[arrszref_make_arrayref]

Asanexample,thefollowingcodecreatesanarray-with-sizecontainingallthedecimaldigits:

valDIGITS=(arrszref)$arrpsz{int}(0,1,2,3,4,5,6,7,8,9)

Notethat arrszref isoverloadedwith arrszref_make_arrpsz .

For reading from and writing to an array-with-size, the function templates arrszref_get_at andarrszref_set_at canbeused,respectively,whichareassignedthefollowinginterfaces:

fun{a:t@ype}

arrszref_get_at(A:arrszref(a),i:size_t):(a)

fun{a:t@ype}

arrszref_set_at(A:arrszref(a),i:size_t,x:a):void

Givenanarray-with-sizeA,anindexiandavaluev, arrszref_get_at(A,i) and arrszref_set_at(A,i,v) canbewrittenas A[i] and A[i]:=v ,respectively.Noticethatarray-boundscheckingisperformedat run-time whenever arrszref_get_at or arrszref_set_at is called, and the exceptionArraySubscriptExn israisedincaseofout-of-boundsarrayaccessbeingdetected.

Asasimpleexample,thefollowingcodeimplementsafunctionthatreversesthecontentofthearrayinsideagivenarray-with-size:

Page 83: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

fun{a:t@ype}

arrszref_reverse

(

A:arrszref(a)

):void=let

//

valn=A.size()

valn2=half(n)

//

funloop

(i:size_t):void=let

in

ifi<n2thenlet

valtmp=A[i]

valni=pred(n)-i

in

A[i]:=A[ni];A[ni]:=tmp;loop(succ(i))

endelse()//endof[if]

end//endof[loop]

//

in

loop(i2sz(0))

end//endof[arrszref_reverse]

Arrays-with-sizecanbeagoodchoiceoverarraysinaprototypeimplementationasitisoftenmoredemanding to programwith arrays. Also, for programmerswho are yet to become familiar withdependenttypes,itisdefinitelyeasiertoworkwitharrays-with-sizethanarrays.WhenprogramminginATS,Ioftenstartoutwitharrays-with-sizeandthenreplacethemwitharrayswhenIcanseeclearbenefitsfromdoingso.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 84: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 85: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 86: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter17.PersistentMatricesA persistent matrix of dimension m by n is just a persistent array of size m*n. Like in C, therepresentation of a matrix in ATS is row-major. In other words, element (i, j) in a matrix ofdimensionmbyniselementi*n+jintheunderlyingarraythatrepresentsthematrix.

GivenaviewtypeVTandtwointegersMandN,thetype matrixref(VT,M,N) isforpersistentmatricesofdimensionMbyNthatcontainelementsoftheviewtypeVT.Thereisnodimensioninformationattachedtomatrixref-valuesexplicitly.TheinterfacesforvariousfunctionsonpersistentmatricescanbefoundintheSATSfileprelude/SATS/matrixref.sats,whichisautomaticallyloadedbyatsopt.

Thefollowingfunctioniscommonlyusedtocreateamatrixref-value:

fun{a:t0p}

matrixref_make_elt{m,n:int}

(m:size_tm,n:size_tn,x0:a):<!wrt>matrixref(a,m,n)

//endof[matrixref_make_elt]

Giventwosizesmandnplusanelementx0, matrixref_make_elt returnsamatrixofdimensionmbyninwhicheachcellisinitializedwiththeelementx0.

Also,thefollowingcastfunctioncanbecalledtoturnanarrayintoamatrix:

castfn

arrayref2matrixref

{a:vt0p}{m,n:nat}(A:arrayref(a,m*n)):<>matrixref(a,m,n)

//endof[arrayref2matrixref]

Foraccessingandupdatingthecontentofamatrix-cell,thefollowingtwofunctions matrixref_get_atand matrixref_set_at canbecalled:

//

fun{a:t0p}

matrixref_get_at

{m,n:int}

(

A:matrixref(a,m,n),i:sizeLt(m),n:size_t(n),j:sizeLt(n)

):<!ref>(a)//endof[matrixref_get_at]

//

fun{a:t0p}

matrixref_set_at

Page 87: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

{m,n:int}

(

A:matrixref(INV(a),m,n),i:sizeLt(m),n:size_tn,j:sizeLt(n),x:a

):<!refwrt>void//endof[matrixref_set_at]

//

Note that it is not enough to just supply the coordinates of amatrix-cell in order to access it; thecolumndimensionofthematrixneedstobesuppliedaswell.

Inthefollowingpresentation,Igiveanimplementationofafunctionthatturnsagivensquarematrixintoitstranspose:

//

extern

fun{a:t0p}

matrixref_transpose

{n:nat}

(

M:matrixref(a,n,n),n:size_t(n)

):void//endof[matrixref_transpose]

//

implement{a}

matrixref_transpose

{n}(M,n)=let

//

macdef

mget(i,j)=

matrixref_get_at(M,,(i),n,,(j))

macdef

mset(i,j,x)=

matrixref_set_at(M,,(i),n,,(j),,(x))

//

funloop

{i,j:nat|

i<j;j<=n

}.<n-i,n-j>.

(

i:size_t(i),j:size_t(j)

):void=

ifj<nthenlet

valx=mget(i,j)

val()=mset(i,j,mget(j,i))

val()=mset(j,i,x)

in

loop(i,j+1)

endelselet

Page 88: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

vali1=succ(i)

in

ifi1<nthenloop(i1,succ(i1))else()

end//endof[if]

//

in

ifn>0thenloop(i2sz(0),i2sz(1))else()

end//endof[matrixref_transpose]

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 89: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 90: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 91: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter18.PersistentMatrices-with-sizeIuse thenamematrix-with-size to refer toapersistentmatrixwithattacheddimension information(thatis,numberofrowsandnumberofcolumns).GivenaviewtypeVT,thetypeforamatrix-with-size that contains M rows and N columns of elements of viewtype VT is mtrxszref(VT, M, N) .Essentially,suchavalueisaboxedrecordofthreecomponentsoftypes arrayref(VT, N) , size_t(M)and size_t(N) .Theinterfacesforvariousfunctionsonpersistentmatrices-with-sizecanbefoundinprelude/SATS/matrixref.sats.

Thefollowingfunctioniscommonlyusedtocreateamatrix-with-size:

fun{a:t0p}

mtrxszref_make_elt(m:size_t,n:size_t,x0:a):mtrxref(a)

//endof[mtrxszref_make_elt]

Given two sizesm and n plus an element x0, mtrxszref_make_elt returns amatrix-with-size of thedimensionmbyninwhicheachmatrix-cellisinitializedwiththegivenelementx0.

Foraccessingandupdatingthecontentofamatrix-cell,thefollowingtwofunctions mtrxszref_get_atand mtrxszref_set_at canbecalled:

fun{a:t0p}

mtrxszref_get_at(M:mtrxszref(a),i:size_t,j:size_t):(a)

fun{a:t0p}

mtrxszref_set_at(M:mtrxszref(a),i:size_t,j:size_t,x:a):void

Given a matrix-with-size M, two indices i and j, and a value v, mtrxszref_get_at(M, i, j) andmtrxszref_set_at(M, i, j, v) can be written as M[i,j] and M[i,j] := v , respectively. Notice thatmatrix-boundschecking isperformedat run-timewhenever mtrxszref_get_at or mtrxszref_set_at iscalled, and theexception MatrixSubscriptExn is raised in caseofout-of-boundsmatrix accessbeingdetected.

As a simple example, the following code implements a function that transpose the content of thematrixinsideagivenmatrix-with-size:

//

extern

fun{a:t0p}

mtrxszref_transpose(M:mtrxszref(a)):void

Page 92: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

//

implement{a}

mtrxszref_transpose

(M)=let

//

valn=M.nrow()

//

val((*void*))=assertloc(M.nrow()=M.ncol())

//

funloop

(

i:size_t,j:size_t

):void=

ifj<nthenlet

valx=M[i,j]

val()=M[i,j]:=M[j,i]

val()=M[j,i]:=x

in

loop(i,succ(j))

endelselet

vali1=succ(i)

in

ifi1<nthenloop(i1,succ(i1))else()

end//endof[if]

//

in

ifn>0thenloop(i2sz(0),i2sz(1))else()

end//endof[mtrxszref_transpose]

Likearrays-with-size,matrices-with-sizeareeasiertoprogramwiththandependentlytypedmatrices.However,thelattercannotonlyleadtomoreeffectiveerrordetectionatcompile-timebutalsomoreefficentcodeexecutionatrun-time.ForsomeoneprogramminginATS,itisquitereasonabletostartoutwithmatrices-with-sizeand thenreplace themwithmatriceswhen thereareclearbenefits fromdoingso.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 93: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 94: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 95: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter19.PersistentHashtablesHashtables are commonly used to implement finite maps. In ATSLIB/libats, there are hashtableimplementations based on linear chaining and linear probing. There is also support for linearhashtablesaswellaspersistenthashtables.The linearonescanbesafely freedby theprogrammer,andthepersistentones(whicharedirectlybasedonlinearones)canonlybesafelyreclaimedthroughgarbagecollection(GC).Inthischapter,Ishowhowpersistenthashtablescanbecreatedandoperatedon.

Supposethatamapisneededformappingkeysoftype key_t toitemsoftype itm_t .ThefollowingcodeessentiallysetsupaninterfaceforcreatingandoperatingonsuchamapbasedonahashtableimplementationinATSLIB/libats:

local

typedef

key=key_tanditm=itm_t

in(*in-of-local*)

#include"libats/ML/HATS/myhashtblref.hats"

end//endof[local]

Pleasefindon-linetheHATSfilementionedinthecode,whichisjustaconveniencewrappermadetosimplifyprogrammingwithhashtables.

Assumethat key_t is string and itm_t is int .Thefollowinglineofcodecreatesahashtablewithitsinitialcapacitysettobe1000:

valmymap=myhashtbl_make_nil(1000)

Note that thecapacity in thiscase is thesizeof thearrayassociatedwith thecreatedhashtable.Theunderlyinghashtable implementation isbasedon linearchaining,and thishashtablecanstoreup to5000 (5*1000) items without need for resizing. When resizing is indeed needed, it is doneautomatically.Thefollowingfewlinesinsertsomekey/itempairsinto mymap :

//

val-~None_vt()=mymap.insert("a",0)

val-~Some_vt(0)=mymap.insert("a",1)

Page 96: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

//

val-~None_vt()=mymap.insert("b",1)

val-~Some_vt(1)=mymap.insert("b",2)

//

val-~None_vt()=mymap.insert("c",2)

val-~Some_vt(2)=mymap.insert("c",3)

//

Thedot-symbol .insert isoverloadedwithafunctionofthename myhashtbl_insert .Givenakeyandan item, mymap.insert inserts the key/item pair into mymap . If the key is in the domain of themaprepresented by mymap before insertion, then the original item associated with the key is returned.Otherwise,noitemisreturned.Ascanbeexpected,thesizeof mymap is3atthispoint:

val()=assertloc(mymap.size()=3)

Thedot-symbol .size isoverloadedwitha functionof thename myhashtbl_get_size ,which returnsthenumberofkey/itempairsstoredinagivenhashtable.Duringthecourseofdebugging,onemaywanttoprintoutthekey/itempairsinagivenhashtable:

//

val()=

fprintln!(stdout_ref,"mymap=",mymap)

//

wherethesymbol fprint isoverloadedwith fprint_myhashtbl .Thenexttwolinesofcodeshowhowsearchwithagivenkeyoperatesonahashtable:

val-~None_vt()=mymap.search("")

val-~Some_vt(1)=mymap.search("a")

Thedot-symbol .search isoverloadedwitha functionof thename myhashtbl_search ,which returnstheitemassociatedwithagivenkeyifitisfound.Thenextfewlinesofcoderemovesomekey/itempairsfrom mymap :

//

val-true=mymap.remove("a")

val-false=mymap.remove("a")

//

val-~Some_vt(2)=mymap.takeout("b")

val-~Some_vt(3)=mymap.takeout("c")

//

Page 97: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Thedot-symbol .remove isoverloadedwithafunctionofthename myhashtbl_remove forremovingakey/itempairofagivenkey.Ifakey/itempairisremoved,thenthefunctionreturnstrue.Otherwise,it returns false to indicates that no key/item pair of the given key is stored in the hashtable beingoperatedon.Thedot-symbol .takeout isoverloadedwithafunctionof thename myhashtbl_takeout ,whichissimilarto myhashtbl_remove exceptingforreturningtheremoveditem.Thenextfewlinesofcodemakeuseofseverallesscommonlyusedfunctionsonhashtables:

//

val()=mymap.insert_any("a",0)

val()=mymap.insert_any("b",1)

val()=mymap.insert_any("c",2)

valkxs=mymap.listize1((*void*))

val((*void*))=fprintln!(stdout_ref,"kxs=",kxs)

valkxs=mymap.takeout_all((*void*))

val((*void*))=fprintln!(stdout_ref,"kxs=",kxs)

//

val()=assertloc(mymap.size()=0)

//

Thedot-symbol .insert_any isoverloadedwitha functionof thename myhashtbl_insert_any , whichalwaysinsertsagivenkey/itempairregardlesswhetherthekeyisalreadyinuse.Oneshouldreallyavoidusingthisfunctionoronlycallitwhenitisabsolutelysurethatthegivenkeyisnotalreadyinuse for otherwise the involved hashtable would be corrupted. The dot-symbols .listize1 and.takeout_all are overloaded with two functions of the names myhashtbl_listize1 andmyhashtbl_takeout_all ,respectively.Bothofthemreturnalistconsistingofallthekey/itempairsinagivenhashtable;theformerkeepsthehashtableunchangedwhilethelatteremptiesit.Last,Ipresentasfollowstheinterfaceforaniteratorgoingoverallthekey/itempairsinagivenhashtable:

//

extern

fun

myhashtbl_foreach_cloref

(

tbl:myhashtbl

,fwork:(key,&(itm)>>_)-<cloref1>void

):void//end-of-function

//

Asanexample,thefollowingcodeprintsoutallthekey/itempairsinagivenhashtable:

//

Page 98: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

val()=

myhashtbl_foreach_cloref

(

mymap

,lam(k,x)=>fprintln!(stdout_ref,"k=",k,"and","x=",x)

)(*myhashtbl_foreach_cloref*)

//

Please find the entirety of the code used in this chapter on-line. Also, there is a hashtable-basedimplementationofsymboltableavailableon-line.

Page 99: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 100: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 101: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter20.Tail-RecursionPleaseseethisarticleforadetailedexplanationontail-recursionandthesupportinATSforturningtail-recursivecallsintolocaljumps.

Page 102: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 103: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 104: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter21.Higher-OrderFunctionsAhigher-order function isone that takesanother functionas its argument.Let us useBT to rangeoverbasetypessuchas int , bool , char , double and string .AsimpletypeTisformedaccordingtothefollowinginductivedefinition:

BTisasimpletype.

(T1,...,Tn)->T0isasimpletypeifT0,T1,...Tnaresimpletypes.

Letorderbeafunctionfromsimpletypestonaturalnumbersdefinedasfollows:

order(BT)=0

order((T1,...,Tn)->T0)=max(order(T0),1+order(T1),...,1+order(Tn))

GivenafunctionfofsomesimpletypeT,letussaythatfisanth-orderfunctioniforder(T)=n.Forinstance,afunctionofthetype(int,int)->intis1st-order,andafunctionofthetypeint->(int->int)is also 1st-order, and a function of the type ((int -> int), int) -> int is 2nd-order. In practice,mostfunctionsare1st-orderandmosthigher-orderfunctionsare2nd-order.

As an example, let us implement as follows a 2nd-order function find_root that takes as its onlyargumentafunctionffromintegerstointegersandsearchesforarootoffbyenumeration:

fnfind_root

(

f:int-<cloref1>int

):int=let

//

funloop

(

f:int-<cloref1>int,n:int

):int=

iff(n)=0thennelse(

ifn<=0thenloop(f,~n+1)elseloop(f,~n)

)//endof[else]//endof[if]

in

loop(f,0)

end//endof[find_root]

Thefunction find_root computesthevaluesoffat0,1,-1,2,-2,etc.untilitfindsthefirstintegernin

Page 105: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

thissequencethatsatisfiesf(n)=0.

Asanotherexample, letusimplementasfollowsthefamousNewton-Raphson'smethodforfindingrootsoffunctionsonreals:

typedef

fdouble=double-<cloref1>double

//

macdefepsilon=1E-6(*precision*)

//

//[f1]isthederivativeof[f]

//

fun

newton_raphson

(

f:fdouble,f1:fdouble,x0:double

):double=let

funloop(

f:fdouble,f1:fdouble,x0:double

):double=let

valy0=fx0

in

ifabs(y0/x0)<epsilonthenx0else

letvaly1=f1x0inloop(f,f1,x0-y0/y1)end

//endof[if]

end//endof[loop]

in

loop(f,f1,x0)

end//endof[newton_raphson]

With newton_raphson , both the square root function and the cubic root function can be readilyimplementedasfollows:

//squarerootfunction

fnsqrt(c:double):double=

newton_raphson(lamx=>x*x-c,lamx=>2.0*x,1.0)

//cubicrootfunction

fncbrt(c:double):double=

newton_raphson(lamx=>x*x*x-c,lamx=>3.0*x*x,1.0)

Higher-orderfunctionscanbeofgreatuseinsupportingaformofcodesharingthatisbothcommonandflexible.Asfunctionargumentsareoftenrepresentedasheap-allocatedclosuresthatcanonlybereclaimedthroughgarbagecollection(GC),higher-orderfunctionsareusedinfrequently,ifatall,ina settingwhereGC is not present. InATS, linear closures, which can be freed explictly in a safe

Page 106: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

manner,areavailabletosupporthigher-orderfunctionsintheabsenceofGC,makingitpossibletoemploy higher-order functions extensively in systems programming (where GC is unavailable orsimplydisallowed).Thedetailsonlinearclosuresaretobegivenelsewhere.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 107: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 108: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 109: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter22.Stream-BasedLazyEvaluationWhilethecoreofATSisbasedoncall-by-valueevaluation, thereisalsodirectsupport inATSforlazy(thatis,call-by-need)evaluation.

There is a special language construct $delay for delaying or suspending the evaluation of anexpression (by forming a thunk), and there is also a special function lazy_force for resuming asuspendedevaluation(representedbyathunk).Theabstracttypeconstructor lazy ofthesort (t@ype)=> type formsa (boxed) typewhenapplied toa type.Givenanexpressionexpof typeT, thevalue$delay(exp) of the type lazy(T) represents thesuspendedevaluationofexp.GivenavalueVof thetype lazy(T) forsometypeT,calling lazy_force onVresumesthesuspendedevaluationrepresentedbyV.Ifthecallreturns,thenthereturnedvalueisoftypeT.Theinterfaceforthefunctiontemplatelazy_force isgivenasfollows:

fun{a:t@ype}lazy_force(lazyval:lazy(a)):<!laz>a

wherethesymbol !laz indicatesaformofeffectassociatedwithlazy-evaluation.Notethatthespecialprefixoperator ! inATSisoverloadedwith lazy_force .

In prelude/SATS/stream.sats, the following types stream_con and stream are declared mutuallyrecursivelyforrepresentinglazystreams:

datatype

stream_con(a:t@ype+)=

|stream_nilof((*void*))|stream_consof(a,stream(a))

wherestream(a:t@ype)=lazy(stream_con(a))

Also, a number of common functions on streams are declared in prelude/SATS/stream.sats andimplementedinprelude/DATS/stream.dats.

ThefollowingcodegivesastandardimplementationofthesieveofEratosthenes:

//

fun

from(n:int):stream(int)=

$delay(stream_cons(n,from(n+1)))

//

funsieve

(

ns:stream(int)

Page 110: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

):<!laz>stream(int)=$delaylet

//

//[val-]meansnowarningmessagefromthecompiler

//

val-stream_cons(n,ns)=!ns

in

stream_cons(n,sieve(stream_filter_cloref<int>(ns,lamx=>xmodn>0)))

end//endof[$delaylet]//endof[sieve]

//

valthePrimes=sieve(from(2))

//

Astreamisconstructedconsistingofalltheintegersstartingfrom2;thefirstelementofthestreamiskeptandallthemultiplesofthiselementareremovedfromthetailofthestream;thisprocessisthenrepeatedonthetailofthestreamrecursively.Clearly,thefinalstreamthusgeneratedconsistsofalltheprimenumbersorderedascendingly.

Thefunctiontemplate stream_filter_cloref isofthefollowinginterface:

fun{a:t@ype}

stream_filter_cloref

(xs:stream(a),pred:a-<cloref>bool):<!laz>stream(a)

//endof[stream_filter_cloref]

Givena streamandapredicate, stream_filter_cloref generatesanother streamconsistingof all theelementsinthegivenstreamthatsatisfythegivenpredicate.

Letusseeanotherexampleoflazyevaluation.ThefollowcodedemonstratesaninterestingapproachtocomputingtheFibonaccinumbers:

//

val_0_=$UNSAFE.cast{int64}(0)

val_1_=$UNSAFE.cast{int64}(1)

//

val//thefollowingvaluesaredefinedmutuallyrecursively

rectheFibs_0

:stream(int64)=$delay(stream_cons(_0_,theFibs_1))//fib0,fib1,...

andtheFibs_1

:stream(int64)=$delay(stream_cons(_1_,theFibs_2))//fib1,fib2,...

andtheFibs_2

:stream(int64)=//fib2,fib3,fib4,...

(

stream_map2_fun<int64,int64><int64>(theFibs_0,theFibs_1,lam(x,y)=>x+y)

)(*endof[val/and/and]*)

Page 111: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

//

Thefunctiontemplate stream_map2_fun isassignedthefollowinginterface:

fun{

a1,a2:t0p}{b:t0p

}stream_map2_cloref

(

xs1:stream(a1),xs2:stream(a2),f:(a1,a2)-<fun>b

):<!laz>stream(b)//endof[stream_map2_cloref]

Giventwostreamsxs1andxs2andabinaryfunctionf, stream_map2_fun formsastreamxssuchthatxs[n](thatis,elementninxs),ifexists,equalsf(xs1[n],xs2[n]),wherenrangesovernaturalnumbers.

Letusseeyetanotherexampleoflazyevaluation.AHammingnumberisapositivenaturalnumberwhoseprimefactorscancontainonly2,3and5.ThefollowingcodeshowsastraightforwardwaytogenerateastreamconsistingofalltheHammingnumbers:

//

val

compare_int_int=

lam(x1:int,x2:int):int=<fun>compare(x1,x2)

//

macdef

merge2(xs1,xs2)=

stream_mergeq_fun<int>(,(xs1),,(xs2),compare_int_int)

//

val

rectheHamming

:stream(int)=$delay

(

stream_cons(1,merge2(merge2(theHamming2,theHamming3),theHamming5))

)(*endof[theHamming]*)

andtheHamming2

:stream(int)=stream_map_fun<int><int>(theHamming,lamx=>2*x)

andtheHamming3

:stream(int)=stream_map_fun<int><int>(theHamming,lamx=>3*x)

andtheHamming5

:stream(int)=stream_map_fun<int><int>(theHamming,lamx=>5*x)

//

Thefunctiontemplate stream_mergeq_fun isgiventhefollowinginterface:

Page 112: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

fun{a:t0p}

stream_mergeq_fun

(

xs1:stream(a),xs2:stream(a),(a,a)-<fun>int

):<!laz>stream(a)//endof[stream_mergeq_fun]

Given twostreamsandanordering (representedbya function)such that the twostreamsare listedascendingly according to the ordering, stream_mergeq_fun returns a stream listed ascendingly thatrepresents theunionof the twogivenstreamssuch thatanyelements in thesecondstreamthatalsooccurinthefirststreamaredropped.

Withstream-basedlazyevaluation,anillusionofinfinitedatacanbereadilycreated.Thisillusionisgiven a simple programming interface plus automatic support for memoization, enabling aprogrammingstylethatcanoftenbebothelegantandintriguing.

Ingeneral,itisdifficulttoestimatethetime-complexityandspace-complexityofaprogrambasedonlazyevaluation.Thisisregardedasaseriousweakness.Withlinearstream-basedlazyevalution,thisweaknesscanessentiallyberemoved.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 113: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 114: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 115: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter23.LinearlyTypedListsA linearly typed list inATS is also referred to as a linear list,which essentially corresponds to asingly-linkedlistinC.Thefollowinglineardatatypedeclarationintroducesalineartype list_vt forlinearlists:

//

datavtype

list_vt(a:vt@ype,int)=

|list_vt_nil(a,0)of()

|{n:nat}

list_vt_cons(a,n+1)of(a,list_vt(a,n))

//

Notethatthekeyword datavtype canalsobewrittenas dataviewtype .Givena(possiblylinear)typeTandanintegerN,thetype list_vt(T,N) isforalistoflengthNthatcontainselementsoftypeT.Theinterfaces for various functions on linear lists can be found in the SATS fileprelude/SATS/list_vt.sats,whichisautomaticallyloadedbyatsopt.

Thefollowingfunction list_vt_length showsa typicalwayofhandlinga linear list in a read-onlysituation:

//

fun

{a:vt@ype}

list_vt_length

(xs:!list_vt(a,n)):int(n)=

(

case+xsof

|list_vt_nil()=>0

|list_vt_cons(x,xs2)=>1+list_vt_length<a>(xs2)

)

//

When xs ismatchedwith the pattern list_vt_nil() , the type of xs is list_vt(a, 0) .When xs ismatchedwith the pattern list_vt_cons(x, xs2) , the type of xs is list_vt(a, N+1) for some naturalnumberNandthetypesof x and xs2 are a and list_vt(a,N) ,respectively.Notethatboth x and xs2arenamesforvalues,andtheirtypesarerequiredtostayunchanged.

Thefollowingfunction list_vt_foreach showsatypicalwayofmodifyingelementsstoredinalinear

Page 116: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

list:

//

fun

{a:vt@ype}

list_vt_foreach

(

xs:!list_vt(a,n)

,fwork:(&(a)>>_)-<cloref1>void

):void=

(

case+xsof

|list_vt_nil()=>()

|@list_vt_cons(x,xs2)=>(fwork(x);list_vt_foreach<a>(xs2,fwork);fold@(xs))

)

//

When xs ismatchedwiththepattern @list_vt_cons(x,xs2) ,thetypeof xs is list_vt(a,N+1) forsomenaturalnumberNandthetypesof x and xs2 are a and list_vt(a,N) ,respectively.Notethatboth xand xs2 are variables (that are a formof left-values).At the beginning of the body following thepattern @list_vt_cons(x,xs2) ,thetypeof xs isassumedtobe list_vt_cons_unfold(L0,L1,L2) ,whichisaviewtypeforalist-nodecreatedbyacallto list_vt_cons suchthatthenodeislocatedatL0andthetwoargumentsof list_vt_cons arelocatedatL1andL2whiletheproofsfortheat-viewsassociatedwithL1andL2areput in thestore forcurrentlyavailableproofs.Therefore,as left-values, x andxs2 haveaddressesL1andL2,respectively,andtheviewsoftheproofsassociatedwithL1andL2area@L1 and list_vt_cons(a,N)@L2 ,respectively.Theapplication fold@(xs) turns xs intoavalueof thetype list_vt(a,N+1) whileconsumingtheproofsassociatedwithL1andL2.Noticethatthetypeof xscanbedifferent fromtheoriginaloneassigned to itafter folding.Thefollowingexampleshowsacaseassuch:

//

fun

{a:vt@ype}

list_vt_append

{m,n:nat}

(

xs:list_vt(a,m),ys:list_vt(a,n)

):list_vt(a,m+n)=let

//

fun

loop{m:nat}

(

Page 117: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

xs:&list_vt(a,m)>>list_vt(a,m+n),ys:list_vt(a,n)

):void=

(

case+xsof

|~list_vt_nil()=>(xs:=ys)

|@list_vt_cons(x,xs2)=>(loop(xs2,ys);fold@(xs))

)

//

in

case+xsof

|~list_vt_nil()=>ys

|@list_vt_cons(x,xs2)=>(loop(xs2,ys);fold@(xs);xs)

end//endof[list_vt_append]

//

Themeaningofthesymbol ~ infrontofapatternistobeexplainedbelow.Theimplementationoflist_vt_append exactlycorrespondstothestandardimplementaionofconcatenatingtwosingly-linkedlistsinC:Letxsandysbetwogivenlists;ifxsisempty,thenysisreturned;otherwise,thelastnodeinxsislocatedandysisstoredinthefieldofthenodereservedforthenextnode.

Thefollowingfunction list_vt_free freesagivenlinearlistcontainingnon-linearelements:

//

fun

{a:vt@ype}

list_vt_free

{n:nat}

(

xs:list_vt(a?,n)

):void=

(

case+xsof

|~list_vt_nil()=>()

|~list_vt_cons(x,xs2)=>list_vt_free<a>(xs2)

)

//

When xs is matched with the pattern ~list_vt_nil() , the type of xs changes to a special oneindicating that xs is no longer available for subsequent use.When xs ismatchedwith the pattern~list_vt_cons(x,xs2) , the typeof xs changesagain toa specialone indicating that xs isno longeravailableforsubsequentuse.Inthelattercase,thetwovaluesrepresentingtheheadandtailofthelistreferredtoas xs canbesubsequentlyreferredtoas x and xs2 ,respectively.Sowhatisreallyfreedhereisthememoryforthefirstlist-nodeinthelistreferredtoas xs .

Page 118: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Pleasefindon-linetheentiretyofthecodeusedinthischapterplussometestingcode.

Page 119: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

II.AdvancedTutorialTopicsTableofContents24.Extvar-Declaration25.LinearClosure-Functions26.AutomaticCodeGeneration

Page 120: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 121: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 122: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter24.Extvar-DeclarationATSputsgreatemphasisoninteractingwithotherprogramminglanguages.

SupposethatIhaveinsomeCcodea(global)integervariableofthename foo andIwanttoincreaseinsomeATScodethevaluestoredin foo by1.Thiscanbedoneasfollows:

valx0=$extval(int,"foo")//getthevalueoffoo

valp_foo=$extval(ptr,"&foo")//gettheaddressoffoo

val()=$UNSAFE.ptr_set<int>(p_foo,x0+1)//updatefoo

wheretheaddress-ofoperator(&)inCisneededfortakingtheaddressof foo .IfIwanttointeractinATSwithalanguagethatdoesnotsupporttheaddress-ofoperator(e.g.,JavaScriptandPython),thenIcandoitasfollows:

extvar"foo"=x0+1

wherethekeyword extvar indicatesthatthestringfollowingitreferstoanexternalvariable(orleft-value)thatshouldbeupdatedwiththevalueoftheexpressionontheright-handsideoftheequalitysymbolfollowingthestring.Ofcourse,thisworksforlanguageslikeCthatdosupporttheaddress-ofoperatoraswell.Thisso-calledextvar-declarationcanalsobewrittenasfollows:

externvar"foo"=x0+1

where extvar expandsinto externvar .

Asforanotherexample,letussupposethat foo2 isarecordvariablethatcontainstwointegerfieldsnamed first and second . Then the following code assigns integers 1 and 2 to these two fields offoo2 :

extvar"foo2.first"=1

extvar"foo2.second"=2

Byitsverynature, thefeatureofextvar-declarationis inherentlyunsafe,anditshouldonlybeusedwithcaution.

Pleasefindon-linetheentiretyofthecodepresentedinthischapter.

Page 123: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 124: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 125: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter25.LinearClosure-FunctionsAclosure-functionisaboxedrecordthatcontainsapointertoanenvlessfunctionplusbindingsthatmapcertainnamesinthebodyoftheenvlessfunctiontovalues.Inpractice,afunctionargumentofahigher-order function isoftena closure-function (insteadof anenvless function).For instance, thefollowinghigher-orderfunction list_map_cloref takesaclosure-functionasitssecondargument:

fun{

a:t@ype}{b:t@ype

}list_map_cloref{n:int}

(xs:list(a,n),f:(a)-<cloref>b):list_vt(b,n)

Closure-functionscanbeeitherlinearornon-linear,andlinearonescanbeexplicitlyfreedinasafemanner.Thekeyword -<cloref> isusedtoformatypefornon-linearclosure-functions.Asavariantof list_map_cloref , the following higher-order function list_map_cloptr takes a linear closure-functionasitssecondargument:

fun{

a:t@ype}{b:t@ype

}list_map_cloptr{n:int}

(xs:list(a,n),f:!(a)-<cloptr>b):list_vt(b,n)

Ascanbeeasilyguessed,thekeyword -<cloptr> isusedtoformatypeforlinearclosure-functions.Note that the symbol ! indicates that the second argument is still available after a call tolist_map_cloptr returns.

Atypicalexamplemakinguseof list_map_cloptr isgivenasfollows:

funfoo{n:int}

(

x0:int,xs:list(int,n)

):list_vt(int,n)=reswhere

{

//

valf=lam(x)=<cloptr>x0+x

valres=list_map_cloptr(xs,f)

val()=cloptr_free($UNSAFE.cast{cloptr(void)}(f))

//

}(*endof[foo]*)

Notethatalinearclosureisfirstcreatedinthebodyofthefunction foo ,anditisexplicitlyfreedafter

Page 126: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

itsuse.Thefunction cloptr_free isgiventhefollowinginterface:

funcloptr_free{a:t0p}(pclo:cloptr(a)):void

where cloptr is abstract. The cast $UNSAFE.cast{cloptr(void)}(f) can certainly be replaced withsomethingsaferbutitwouldmakeprogrammingmorecurbersome.

There is also some interesting interaction between currying and linear closure-functions. Infunctional programming, currying means turning a function taking multiple argumentssimutaneously into a corresponding one that takes these arguments sequentially. For instance, thefunction acker2 inthefollowingcodeisacurriedversionofthefunction acker ,which implementsthefamousAckermannfunction(thatisrecursivebutnotprimitiverecursive):

fun

acker(m:int,n:int):int=

(

case+(m,n)of

|(0,_)=>n+1

|(m,0)=>acker(m-1,1)

|(_,_)=>acker(m-1,acker(m,n-1))

)(*endof[acker]*)

funacker2(m:int)(n:int):int=acker(m,n)

Suppose that we apply acker2 to two integers 3 and 4: acker2(3)(4) ; the application acker2(3)

evaluatestoa(non-linear)closure-function;theapplicationofthisclosure-functionto4evaluatestoacker(3,4) ,whichfurtherevaluatestotheinteger125.Notethattheclosure-functiongeneratedfromevaluating acker2(3) becomesaheap-allocatedvaluethatisnolongeraccessibleaftertheevaluationof acker2(3)(4) finishes,and thememoryforsuchavaluecanonly tobesafelyreclaimedthroughgarbagecollection(GC).

Itisalsopossibletodefineacurriedversionof acker asfollows:

funacker3(m:int)=lam(n:int):int=<cloptr1>acker(m,n)

While the evaluation of acker3(3)(4) yields the same result as acker2(3)(4) , the compiler of ATS(ATS/Postiats) inserts code that automatically frees the linear closure-function generated fromevaluating acker3(3) aftertheevaluationof acker3(3)(4) finishes.

InATS1,linearclosure-functionsplayapivotalroleinsupportingprogrammingwithhigher-order

Page 127: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

functions in theabsenceofGC.Duetoadvancedsupportfor templates inATS2, theroleplayedbylinear closure-functions in ATS1 is greatly diminished. However, if closure-functions need to bestoredinadatastructurebutGCisunavailableorundesirable,thenusinglinearclosure-functionscanleadtoasolutionthatavoidstheriskofgeneratigmemoryleaksatrun-time.

Pleasefindon-linetheentiretyofthecodeusedinthischapter.

Page 128: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 129: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer
Page 130: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Chapter26.AutomaticCodeGenerationInpractice,oneoftenencountersaneedtowriteboilerplatecodeorcodethattendstofollowcertainclearly recognizable patterns. It is commonly seen that meta-programming (of various forms) isemployed toautomaticallygenerate suchcode, thusnotonly increasingprogrammingproductivitybut also potentially eliminating bugs that would otherwise be introduced due to manual codeconstruction.

Inthefollowingpresentation,IamtoshowthattheATScompilercanbedirectedtogeneratethecodeforcertainfunctionsonvaluesofadeclareddatatype.Followingisthedatatypeusedforillustration:

//

datatypeexpr=

|Intofint

|Varofstring

|Addof(expr,expr)

|Subof(expr,expr)

|Mulof(expr,expr)

|Divof(expr,expr)

|Ifgtzof(expr,expr,expr)//ifexpr>0then...else...

|Ifgtezof(expr,expr,expr)//ifexpr>=0then...else...

//

whichisforsomekindofabstractsyntaxtreesrepresentingarithmeticexpressions.

Page 131: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Generatingadatcon-function

Givenadatatype, itsdatcon-function is theone that takesavalueof thedatatypeand thenreturnsastringrepresentingthenameofthe(outmost)constructorintheconstructionofthevalue.Wecanusethe following directive to indicate (to theATS compiler) that the datcon-function for the datatypeexpr needstobegenerated:

#codegen2("datcon",expr)

Bydefault,thenameofthegeneratedfunctionis datcon_expr .Ifadifferentnameisneeded,itcanbesupplied as the third argument of the #codegen2 -directive. For instance, the following directiveindicatesthatthegeneratedfunctionisofthegivenname my_datcon_expr :

#codegen2("datcon",expr,my_datcon_expr)

Assumethatafileofthenameexpr.datscontainsthefollowingdirective(asatopleveldeclaration):

#codegen2("datcon",expr)

and the definition for expr is accessible at the point where the codegen2 -directive is declared. Byexecutingthefollowingcommand-line:

patscc--codegen-2-dexpr.dats

wecanseesomeoutputofATScodethatimplements datcon_expr :

(**************)

//

implement

{}(*tmp*)

datcon_expr

(arg0)=

(

case+arg0of

|Int_=>"Int"

|Var_=>"Var"

|Add_=>"Add"

|Sub_=>"Sub"

|Mul_=>"Mul"

|Div_=>"Div"

|Ifgtz_=>"Ifgtz"

|Ifgtez_=>"Ifgtez"

Page 132: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

)

//

(**************)

If the output needs to be stored in a file of the name fprint_expr.hats ,we can issue the followingcommand-line:

patscc-ofprint_expr.hats--codegen-2-dexpr.dats

Note that the funtion template datcon_expr is required to be declared somewhere in order for thegeneratedcodetobecompiledproperly:

fun{}datcon_expr:(expr)->string//afunctiontemplate

Pleasefindon-line theentiretyof thispresentedexampleplusaMakefile (for illustrating thecodegenerationprocess).

Page 133: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Generatingadatcontag-function

Adatcontag-functionisverysimilartoadatcon-function.Givenadatatype,itsdatcontag-functionistheonethattakesavalueofthedatatypeandthenreturnsthetag(whichisasmallinteger)assignedtothe (outmost) constructor in the construction of the value.We can use the following directive toindicate(totheATScompiler)thatthedatcontag-functionforthedatatype expr needstobegenerated:

#codegen2("datcontag",expr)

Bydefault,thenameofthegeneratedfunctionis datcontag_expr .Ifadifferentnameisneeded,itcanbe supplied as the third argument of the #codegen2 -directive. For instance, the following directiveindicatesthatthegeneratedfunctionisofthegivenname my_datcontag_expr :

#codegen2("datcontag",expr,my_datcontag_expr)

ThefollowingATScodeisexpectedtobegeneratedthatimplements datcontag_expr :

(**************)

//

implement

{}(*tmp*)

datcontag_expr

(arg0)=

(

case+arg0of

|Int_=>0

|Var_=>1

|Add_=>2

|Sub_=>3

|Mul_=>4

|Div_=>5

|Ifgtz_=>6

|Ifgtez_=>7

)

//

(**************)

Notethatthefuntiontemplate datcontag_expr isrequiredtobedeclaredsomewhereinorderfor thegeneratedcodetobecompiledproperly:

fun{}datcontag_expr:(expr)->intGte(0)//afunctiontemplate

Page 134: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Pleasefindon-line theentiretyof thispresentedexampleplusaMakefile (for illustrating thecodegenerationprocess).

Page 135: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

Generatingafprint-function

A fprint-function takes a file-handle (of the type FILEref ) and a value and then outputs a textrepresentationofthevaluetothefile-handle.Givenadatatype,oneisofteninneedofafunctionthatcanoutputcertainkindoftextrepresentationforvaluesofthisdatatype.Forinstance,suchafunctioncanbeofgreatuseindebugging.

Letusfirstdeclareafunctiontemplate fprint_expr asfollows:

fun{}fprint_expr:(FILEref,expr)->void//afunctiontemplate

Wecanthenusethedirectivebelowtoindicate(totheATScompiler)thatthefprint-functionforthedatatype expr needstobegenerated:

#codegen2("fprint",expr,fprint_expr)

The third argument of the codegen2 -directive can be omitted in this case as it coincides with thedefault.Thegeneratedcodethatimplements fprint_expr islistedasfollows:

(**************)

//

extern

fun{}

fprint_expr$Int:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Var:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Add:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Sub:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Mul:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Div:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz:$d2ctype(fprint_expr<>)

extern

Page 136: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

fun{}

fprint_expr$Ifgtez:$d2ctype(fprint_expr<>)

//

(**************)

//

implement{}

fprint_expr

(out,arg0)=

(

case+arg0of

|Int_=>fprint_expr$Int<>(out,arg0)

|Var_=>fprint_expr$Var<>(out,arg0)

|Add_=>fprint_expr$Add<>(out,arg0)

|Sub_=>fprint_expr$Sub<>(out,arg0)

|Mul_=>fprint_expr$Mul<>(out,arg0)

|Div_=>fprint_expr$Div<>(out,arg0)

|Ifgtz_=>fprint_expr$Ifgtz<>(out,arg0)

|Ifgtez_=>fprint_expr$Ifgtez<>(out,arg0)

)

//

(**************)

//

extern

fun{}

fprint_expr$sep:(FILEref)->void

implement{}

fprint_expr$sep(out)=fprint(out,",")

//

extern

fun{}

fprint_expr$lpar:(FILEref)->void

implement{}

fprint_expr$lpar(out)=fprint(out,"(")

//

extern

fun{}

fprint_expr$rpar:(FILEref)->void

implement{}

fprint_expr$rpar(out)=fprint(out,")")

//

extern

fun{a:t0p}

fprint_expr$carg:(FILEref,INV(a))->void

implement{a}

fprint_expr$carg(out,arg)=fprint_val<a>(out,arg)

//

(**************)

Page 137: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

//

extern

fun{}

fprint_expr$Int$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Int$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Int$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Int$arg1:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Int(out,arg0)=

{

//

val()=fprint_expr$Int$con<>(out,arg0)

val()=fprint_expr$Int$lpar<>(out,arg0)

val()=fprint_expr$Int$arg1<>(out,arg0)

val()=fprint_expr$Int$rpar<>(out,arg0)

//

}

implement{}

fprint_expr$Int$con(out,_)=fprint(out,"Int")

implement{}

fprint_expr$Int$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Int$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Int$arg1(out,arg0)=

letval-Int(arg1)=arg0infprint_expr$carg(out,arg1)end

//

extern

fun{}

fprint_expr$Var$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Var$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Var$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Var$arg1:$d2ctype(fprint_expr<>)

//

Page 138: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

implement{}

fprint_expr$Var(out,arg0)=

{

//

val()=fprint_expr$Var$con<>(out,arg0)

val()=fprint_expr$Var$lpar<>(out,arg0)

val()=fprint_expr$Var$arg1<>(out,arg0)

val()=fprint_expr$Var$rpar<>(out,arg0)

//

}

implement{}

fprint_expr$Var$con(out,_)=fprint(out,"Var")

implement{}

fprint_expr$Var$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Var$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Var$arg1(out,arg0)=

letval-Var(arg1)=arg0infprint_expr$carg(out,arg1)end

//

extern

fun{}

fprint_expr$Add$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Add$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Add$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Add$sep1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Add$arg1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Add$arg2:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Add(out,arg0)=

{

//

val()=fprint_expr$Add$con<>(out,arg0)

val()=fprint_expr$Add$lpar<>(out,arg0)

val()=fprint_expr$Add$arg1<>(out,arg0)

val()=fprint_expr$Add$sep1<>(out,arg0)

Page 139: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

val()=fprint_expr$Add$arg2<>(out,arg0)

val()=fprint_expr$Add$rpar<>(out,arg0)

//

}

implement{}

fprint_expr$Add$con(out,_)=fprint(out,"Add")

implement{}

fprint_expr$Add$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Add$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Add$sep1(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Add$arg1(out,arg0)=

letval-Add(arg1,_)=arg0infprint_expr$carg(out,arg1)end

implement{}

fprint_expr$Add$arg2(out,arg0)=

letval-Add(_,arg2)=arg0infprint_expr$carg(out,arg2)end

//

extern

fun{}

fprint_expr$Sub$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Sub$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Sub$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Sub$sep1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Sub$arg1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Sub$arg2:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Sub(out,arg0)=

{

//

val()=fprint_expr$Sub$con<>(out,arg0)

val()=fprint_expr$Sub$lpar<>(out,arg0)

val()=fprint_expr$Sub$arg1<>(out,arg0)

val()=fprint_expr$Sub$sep1<>(out,arg0)

val()=fprint_expr$Sub$arg2<>(out,arg0)

Page 140: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

val()=fprint_expr$Sub$rpar<>(out,arg0)

//

}

implement{}

fprint_expr$Sub$con(out,_)=fprint(out,"Sub")

implement{}

fprint_expr$Sub$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Sub$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Sub$sep1(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Sub$arg1(out,arg0)=

letval-Sub(arg1,_)=arg0infprint_expr$carg(out,arg1)end

implement{}

fprint_expr$Sub$arg2(out,arg0)=

letval-Sub(_,arg2)=arg0infprint_expr$carg(out,arg2)end

//

extern

fun{}

fprint_expr$Mul$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Mul$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Mul$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Mul$sep1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Mul$arg1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Mul$arg2:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Mul(out,arg0)=

{

//

val()=fprint_expr$Mul$con<>(out,arg0)

val()=fprint_expr$Mul$lpar<>(out,arg0)

val()=fprint_expr$Mul$arg1<>(out,arg0)

val()=fprint_expr$Mul$sep1<>(out,arg0)

val()=fprint_expr$Mul$arg2<>(out,arg0)

val()=fprint_expr$Mul$rpar<>(out,arg0)

Page 141: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

//

}

implement{}

fprint_expr$Mul$con(out,_)=fprint(out,"Mul")

implement{}

fprint_expr$Mul$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Mul$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Mul$sep1(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Mul$arg1(out,arg0)=

letval-Mul(arg1,_)=arg0infprint_expr$carg(out,arg1)end

implement{}

fprint_expr$Mul$arg2(out,arg0)=

letval-Mul(_,arg2)=arg0infprint_expr$carg(out,arg2)end

//

extern

fun{}

fprint_expr$Div$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Div$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Div$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Div$sep1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Div$arg1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Div$arg2:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Div(out,arg0)=

{

//

val()=fprint_expr$Div$con<>(out,arg0)

val()=fprint_expr$Div$lpar<>(out,arg0)

val()=fprint_expr$Div$arg1<>(out,arg0)

val()=fprint_expr$Div$sep1<>(out,arg0)

val()=fprint_expr$Div$arg2<>(out,arg0)

val()=fprint_expr$Div$rpar<>(out,arg0)

//

Page 142: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

}

implement{}

fprint_expr$Div$con(out,_)=fprint(out,"Div")

implement{}

fprint_expr$Div$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Div$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Div$sep1(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Div$arg1(out,arg0)=

letval-Div(arg1,_)=arg0infprint_expr$carg(out,arg1)end

implement{}

fprint_expr$Div$arg2(out,arg0)=

letval-Div(_,arg2)=arg0infprint_expr$carg(out,arg2)end

//

extern

fun{}

fprint_expr$Ifgtz$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$sep1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$sep2:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$arg1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$arg2:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtz$arg3:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Ifgtz(out,arg0)=

{

//

val()=fprint_expr$Ifgtz$con<>(out,arg0)

val()=fprint_expr$Ifgtz$lpar<>(out,arg0)

Page 143: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

val()=fprint_expr$Ifgtz$arg1<>(out,arg0)

val()=fprint_expr$Ifgtz$sep1<>(out,arg0)

val()=fprint_expr$Ifgtz$arg2<>(out,arg0)

val()=fprint_expr$Ifgtz$sep2<>(out,arg0)

val()=fprint_expr$Ifgtz$arg3<>(out,arg0)

val()=fprint_expr$Ifgtz$rpar<>(out,arg0)

//

}

implement{}

fprint_expr$Ifgtz$con(out,_)=fprint(out,"Ifgtz")

implement{}

fprint_expr$Ifgtz$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Ifgtz$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Ifgtz$sep1(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Ifgtz$sep2(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Ifgtz$arg1(out,arg0)=

letval-Ifgtz(arg1,_,_)=arg0infprint_expr$carg(out,arg1)end

implement{}

fprint_expr$Ifgtz$arg2(out,arg0)=

letval-Ifgtz(_,arg2,_)=arg0infprint_expr$carg(out,arg2)end

implement{}

fprint_expr$Ifgtz$arg3(out,arg0)=

letval-Ifgtz(_,_,arg3)=arg0infprint_expr$carg(out,arg3)end

//

extern

fun{}

fprint_expr$Ifgtez$con:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtez$lpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtez$rpar:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtez$sep1:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtez$sep2:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtez$arg1:$d2ctype(fprint_expr<>)

extern

Page 144: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

fun{}

fprint_expr$Ifgtez$arg2:$d2ctype(fprint_expr<>)

extern

fun{}

fprint_expr$Ifgtez$arg3:$d2ctype(fprint_expr<>)

//

implement{}

fprint_expr$Ifgtez(out,arg0)=

{

//

val()=fprint_expr$Ifgtez$con<>(out,arg0)

val()=fprint_expr$Ifgtez$lpar<>(out,arg0)

val()=fprint_expr$Ifgtez$arg1<>(out,arg0)

val()=fprint_expr$Ifgtez$sep1<>(out,arg0)

val()=fprint_expr$Ifgtez$arg2<>(out,arg0)

val()=fprint_expr$Ifgtez$sep2<>(out,arg0)

val()=fprint_expr$Ifgtez$arg3<>(out,arg0)

val()=fprint_expr$Ifgtez$rpar<>(out,arg0)

//

}

implement{}

fprint_expr$Ifgtez$con(out,_)=fprint(out,"Ifgtez")

implement{}

fprint_expr$Ifgtez$lpar(out,_)=fprint_expr$lpar(out)

implement{}

fprint_expr$Ifgtez$rpar(out,_)=fprint_expr$rpar(out)

implement{}

fprint_expr$Ifgtez$sep1(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Ifgtez$sep2(out,_)=fprint_expr$sep<>(out)

implement{}

fprint_expr$Ifgtez$arg1(out,arg0)=

letval-Ifgtez(arg1,_,_)=arg0infprint_expr$carg(out,arg1)end

implement{}

fprint_expr$Ifgtez$arg2(out,arg0)=

letval-Ifgtez(_,arg2,_)=arg0infprint_expr$carg(out,arg2)end

implement{}

fprint_expr$Ifgtez$arg3(out,arg0)=

letval-Ifgtez(_,_,arg3)=arg0infprint_expr$carg(out,arg3)end

//

(**************)

Thecodefor fprint_expr isentirelytemplate-based.Thisstylemakesthecodeextremelyflexibleforadaption through template re-mplementation. As the datatype expr is recursively defined, thefollowingtemplateimplementationneedstobeaddedinordertomake fprint_expr work:

Page 145: A Tutorial on Programming Features in ATSats-lang.github.io/DOCUMENT/ATS2TUTORIAL/PDF/main_epub.pdf · 2020-05-05 · Preface This tutorial covers a variety of issues that a programmer

implementfprint_expr$card<expr>=fprint_expr

Forinstance,applying fprint_expr totheexpression Add(Int(10),Mul(Int(1),Int(2))) outputsthesametextrepresentation.Asanexampleofadaptation,letusaddthefollowingtemplateimplementations:

implement

fprint_expr$Add$con<>(_,_)=()

implement

fprint_expr$Add$sep1<>(out,_)=fprint!(out,"+")

When fprint_expr isappliedtotheexpression Add(Int(10),Mul(Int(1),Int(2))) thistime,theoutputisexpectedtoread (Int(10)+Mul(Int(1),Int(2))) .

Afterproperadaptationisdone,onecanintroducea(non-template)functionasfollows:

//

extern

fun

my_fprint_expr(FILEref,expr):void

implement

my_fprint_expr(out,x)=fprint_expr<>(out,x)

//

Inthisway,onlyoneinstanceof fprint_expr iscompiledevenifrepeatedcallsto my_fprint_expr aremade.

Pleasefindon-line theentiretyof thispresentedexampleplusaMakefile (for illustrating thecodegenerationprocess).

Done.