liva · 2016. 8. 25. · liva is a general-purpose programming language and a lite version of java....

122
LIVA A Lite Version of Java Shanqi Lu Jiafei Song Zihan Jiao Yanan Zhang Hyoyoon Kate Kim sl4017 js4984 zj2203 yz3054 hk2870

Upload: others

Post on 05-Feb-2021

1 views

Category:

Documents


0 download

TRANSCRIPT

  • LIVAALiteVersionofJava

    ShanqiLu JiafeiSong ZihanJiao YananZhang HyoyoonKateKimsl4017 js4984 zj2203 yz3054 hk2870

  • 1

    Table of Contents

    Chapter1Introduction...........................................................................................................3

    Chapter2LanguageTutorial...................................................................................................32.1EnvironmentSetup.....................................................................................................................32.2Runandtest...............................................................................................................................32.3HelloWorld................................................................................................................................42.4Anothersmallprogram...............................................................................................................5

    Chapter3LanguageManual...................................................................................................53.1INTRODUCTION..........................................................................................................................53.2LEXICALCONVENTIONS...............................................................................................................6

    3.2.1WhiteSpace................................................................................................................................63.2.2Comments..................................................................................................................................63.2.3Identifiers....................................................................................................................................73.2.4Keyword......................................................................................................................................73.2.5Literals........................................................................................................................................73.2.6Separators...................................................................................................................................83.2.7Operators....................................................................................................................................8

    3.3Types..........................................................................................................................................93.3.1PrimitiveTypes...........................................................................................................................93.3.2ReferenceTypes.......................................................................................................................10

    3.4Expressions...............................................................................................................................113.4.1Evaluation,Denotation,andResult..........................................................................................113.4.2TypeofanExpression...............................................................................................................123.4.3EvaluationOrder.......................................................................................................................123.4.4LexicalLiterals...........................................................................................................................123.4.5TheArithmeticOperations.......................................................................................................133.4.6TheRelationalOperations........................................................................................................133.4.7TheBitwiseandConditionalOperations:.................................................................................143.4.8MethodInvocationExpressions...............................................................................................143.4.9ArrayAccessExpressions..........................................................................................................143.4.10Assignment.............................................................................................................................15

    3.5Statements...............................................................................................................................153.5.1ExpressionStatements.............................................................................................................153.5.2DeclarationStatements............................................................................................................153.5.3ControlFlowStatements..........................................................................................................163.5.4MethodCreationandMethodCall...........................................................................................183.5.5PrinttoConsole........................................................................................................................193.5.6EmptyStatement......................................................................................................................20

    3.6Classes......................................................................................................................................203.6.1ClassDeclarations.....................................................................................................................203.6.2ObjectInstantiation..................................................................................................................20

  • 2

    3.6.3Inheritance................................................................................................................................21

    Chapter4ProjectPlan...........................................................................................................224.1Plan..........................................................................................................................................224.2Timeline...................................................................................................................................224.3RolesandResponsibilities.........................................................................................................234.4SoftwareEnvironment..............................................................................................................234.5ProjectProlog...........................................................................................................................23

    Chapter5ArchitectureDesign...............................................................................................245.1Overview..................................................................................................................................245.2Thescanner..............................................................................................................................245.3TheParser................................................................................................................................245.4TheSemanticChecker...............................................................................................................255.5TheCodeGenerator.................................................................................................................26

    Chapter6TestPlan...............................................................................................................266.1Reasonforchoosingtestcases.................................................................................................266.2Unittesting...............................................................................................................................276.3Integrationtesting....................................................................................................................276.4Automation..............................................................................................................................276.5Representativesourceprograms..............................................................................................27

    Chapter7LessonsLearned....................................................................................................53

    Chapter8Appendix...............................................................................................................55

  • 3

    Chapter 1 Introduction Livaisageneral-purposeprogramminglanguageandaliteversionofJava.Havingrealizedthatthe focus of this project should be applying compiler design theories in practice rather thaninnovation,wedecidedtodevelopalanguagethathasthesimilarsyntaxandabstractdatatypesinJava.Pastprojectsrelatedtogeneral-purposelanguagesallhavetheirowninterestingfeatureslikeCpi (2013) implementedadata typecalled“struct”andDice (2015)developedtheirownversionofinheritancemechanism.Ourpreferenceistodevelopsomebasicfeaturesandobject-orientedmodelthatresemblesJava.ThislanguageiscompileddowntoLLVM.Unlikedomain-specificprogramminglanguagesaredesignedforspecificfields,ourlanguageisdesignedforgeneralpurpose,henceservingasaportablelanguagethatrunsonmanyplatformsaslongasLLVMisrunnable.ProgramswritteninLivawilllooklikeJavainmanywaysincludingvariable declaration and class declaration. Common algorithms like GCD can be easilyimplementedusingourlanguage.

    Chapter 2 Language Tutorial 2.1EnvironmentSetupThiscompilerhasbeenbuiltandtestedonUbuntu16.04andOSX.PrerequisitesincludeOCaml,LLVM,Opam,etc.InstructionsonhowtoinstallthenecessarypackagesunderUbuntu16.04isshownbelow:sudo apt-get install -y ocaml m4 llvm opam opam init opam install llvm.3.6 ocamlfind eval `opam config env` ForinstallationunderOSX,pleaserefertotheMicroCcompiler’sREADMEfilewhichcanbefoundathttp://www.cs.columbia.edu/~sedwards/classes/2016/4115-summer/index.html 2.2Runandtest First,makesurethatyouareinthe“Liva”rootdirectory.Totestthecompilerbyusingthetestsuit,followtheinstructionsbelow:$makeliva-ocamlfindocamlopt-c-packagellvmast.ml

  • 4

    -ocamlfindocamlopt-c-packagellvmsast.ml-ocamlyaccparser.mly-ocamlc-cast.ml-ocamlc-cparser.mli-ocamlfindocamlopt-c-packagellvmparser.ml-ocamllexscanner.mll127states,6605transitions,tablesize27182bytes-ocamlfindocamlopt-c-packagellvmscanner.ml-ocamlfindocamlopt-c-packagellvmsemant.ml-ocamlfindocamlopt-c-packagellvmcodegen.ml-ocamlfindocamlopt-c-packagellvmliva.ml-ocamlfindocamlopt-linkpkg-packagellvm-packagellvm.analysisast.cmxsast.cmxparser.cmx-scanner.cmxsemant.cmxcodegen.cmxliva.cmx-olivaYoumayneedtorun“chmod+xtestall.sh”tounlocktheshellscript.$./testall.sh-ntest-add...OK-ntest-and...OK...-nfail-sub...OK-nfail-while1...OK2.3HelloWorldTotestasimple“HelloWorld”program,youneedto:1compilethecompiler(thishavealreadybeendoneusing“makeliva”inthepreviousstep)2outputgeneratedLLVMIRcodetoa“*.ll”file3run“*.ll”filehello_world.liva:

    Copytheabovecodetoanemptyfilenamed“hello_world.liva”,thenrun:

    class test { void main () { print ("Hello World!\n"); } }

  • 5

    $./liva<hello_world.liva>hello_world.ll$llihello_world.llThisshouldprintoutthedesiredresult“HelloWorld!”.2.4AnothersmallprogramThisisanexampletoshowthatLivasupportsobject-orientedparadigm.Writeanothersmallprogramandtestit.test.liva:

    $./liva<test.liva>test.ll$llitest.llresult=110

    Chapter 3 Language Manual 3.1INTRODUCTION

    class calculator{ int addition(int x, int y){ int z; z = x + y; return(z); } } class test { void main(){ int result; class calculator obj = new calculator(); result = obj.addition(31,79); print ("result=",result,"\n"); } }

  • 6

    LivaisageneralpurposeprogramminglanguageandaliteversionofJava.Itisdesignedtoletprogrammerswhoarefamiliarwithclass-basedlanguagestofeelcomfortablewithdevelopingcommonalgorithmslikeGCD.ItisliteinthesensethatitmaintainssomebutnotallfeaturesinJava. It has the similar syntax and abstract data types in Java and supports object-orientedparadigmandinheritance.However,genericsandnestedclassesarebeyondthescopeofthisproject,hencetheyarenottobeimplemented.The Liva programming language is strongly typed. The compiler checks whether argumentspassedtoafunctionmatchexpectedtypesandreturnanerrorifnot.ItisaportablelanguageandcompileddowntoLLVM.Thislanguagereferencemanualisorganizedasfollows:

    • Section3.2describesthelexicalconventionsoftheLivaprogramminglanguage.• Section3.3describestypes.Typesaredividedintotwocategories:primitivetypesand

    referencetypes.• Section3.4describesclassesincludingclassdeclarationsandinheritance.• Section3.5describesstatements.• Section3.6describesexpressions.

    3.2LEXICALCONVENTIONSThischapterspecifiesthelexicalconventionsofLivaprogramminglanguage.Acompilertakesaprogramwhichconsistsofasequenceofcharactersandreduceittoasequenceofelements,which are tokens,white space and comments. The tokens are identifiers, keywords, literals,separators,andoperators.

    Element:WhiteSpace|Comment|Token

    Token:Identifier|Keyword|Literal|Separator|Operator

    3.2.1WhiteSpaceWhite space in Liva is defined as space character, tab character, form feed character(page-breaking)andlineterminatorcharacter.Whitespacecharactersareignoredbyacompilerexceptastheyservetoseparatetokens.3.2.2CommentsThereisonekindofcomments:/*text*/

  • 7

    Allcharactersfrom“/*”to“*/”areignored.3.2.3IdentifiersAnidentifierisasequenceofletters,digitsandunderscore‘_’.Itcanonlybeginwithaletter.Identifiersarethenamesofvariables,methodsandclasses.Theyarecase-sensitive.3.2.4KeywordKeywordsarereservedandcannotbeusedasidentifiers.

    • Keyword:

    3.2.5LiteralsLiteralsaresyntacticrepresentationsofnumeric,character,booleanorstringdata.Theyareusedforrepresentingvaluesinprograms.3.2.5.1BooleanLiteralsTherearetwobooleanliterals:

    • true representsatrueBooleanvalue• false representsafalseBooleanvalue

    3.2.5.2IntegerLiteralsInteger numbers in Liva are in decimal format. Negative decimal numbers such as -10 areactuallyexpressionsconsistingoftheoperator‘-’andintegerliteral.Theprimitivetypeofintegerliteralisint.3.2.5.3FloatingPointLiteralsFloatingpointnumbersareexpressedasdecimalfractionsandconsistof:

    for new if boolean this break

    implements else return while float extendsint char void class

  • 8

    • anoptional‘+’or‘-’sign;ifomitted,thevalueispositive,• thefollowingformat

    Format Example

    integerdigits . integerdigits 17.31

    3.2.5.4CharacterLiteralsCharacterliteralsaresurroundedbysinglequotes:'a', '#'3.2.5.5StringLiteralsStringliteralsbeginwithadoublequotecharacter",followedbyzeroormorecharactersandaterminatingdoublequote"Withinstringliterals,therecanbeescapesequencesbutnotunescapednewline.3.2.5.6EscapeSequencesforCharacterandStringLiteralsAnescapesequenceisusedtorepresentaspecialcharacter.Itbeginswithabackslashcharacter(\),whichindicatesthatthefollowingcharactershouldbetreatedspecially.Escapesequencesarelistedinthetablebelow.Name CharacterTAB \tnewline \ndoublequote \”singlequote \’backslash \\3.2.6SeparatorsSeparatorsaresymbolsusedforseparatingtokens.

    3.2.7Operators

    { } ( ) ; , .

  • 9

    Theexpressionsectionofthismanualwillexplainbehaviorsoftheseoperators.Hereisalistofallthesupportedoperators.

    3.3TypesTheLivaprogramminglanguagesupportstwokindsoftypes:primitivetypesandreferencetypes.Therearealsotwokindsofdatavalues:primitivevaluesandreferencevaluesaccordingly.Primitivetypesarebooleantypesandnumerictypes.Referencetypesareclasstypesandarraytypes.3.3.1PrimitiveTypesPrimitivetypesarepredefinedbytheLivaprogramminglanguage.Theirnamesarereservedkeywords.3.3.1.1IntegralTypesTheintegraltypesareintandchar.Theintegerdatatypeisa32-bitsequenceofdigits,whichhasaminimumvalueof-2^31andamaximumvalueof 2^31-1.An integer literal is a sequenceof digits precededby anoptionalnegativesign.Azerovaluecannotbeprecededbyanegativesign.

    3.3.1.2CharTypesThechardatatypeisasingle8-bitASCIIcharacter.Theirvaluesrangefrom‘0x00’to‘0x7F’.

    3.3.1.3Floating-PointTypes

    int x = 10; int y = -50; int z = 0;

    char x = 'a';

    = > < ! == >=

  • 10

    Thefloating-pointdatatypeisasigned-precision32-bitformatvalues.

    3.3.1.4TheBooleanTypeThebooleandata type has twopossible values:trueandfalse. A boolean is its own type andcannotbecomparedtoanon-booleanvariable.Therefore,expression“true==1”wouldleadtoanerror.

    3.3.2ReferenceTypesTherearetwokindsofreferencetypes:classtypesandarraytypes.3.3.2.1ClasstypesAclasstypeconsistsofanidentifierwhichisoptionallyfollowedbyparameters.Aclassisanextensibletemplateforcreatingobjects.SeeChapter6togetmoreexplanationaboutclassandobject.3.3.2.2ArraytypesArrayisaspecialtype.Anarraycontainsanumberofelementswithprimitivetypes.Allelementsinanarraymusthavethesametypes.

    3.3.2.3VoidtypeThevoidtypeisusedtoindicateanemptyreturnvaluefromafunctioncall.Forexample,amainfunctiondoesnothaveareturnvalue.Itisdeclaredinthefollowingway.

    float x = 1.5; float y = -5.1; float z = 2.0;

    boolean x = true; boolean y = false;

    int[] ai; char[] ac = { 'a', 'b', 'c', ' ' };

    void main{ }

  • 11

    3.4ExpressionsMuch of the work in a program is done by evaluatingexpressions, such as assignments tovariables,orfortheirvalues,whichcanbeusedasargumentsoroperandsinlargerexpressions,ortoaffecttheexecutionsequenceinstatements,orboth.Thischapterspecifiesthemeaningsofexpressionsandtherulesfortheirevaluation.

    3.4.1Evaluation,Denotation,andResultLiva evaluates a larger expression by evaluating smaller parts of it.When an expression in aprogramisevaluated(executed),theresultdenotesoneofthreethings:

    • Avariable

    • Avalue

    • Nothing(forvoidfunctionsandmethods)

    Anexpressiondenotesnothingifandonlyifitisamethodinvocationthatinvokesamethodthatdoesnotreturnavalue,thatis,amethoddeclaredvoid.Suchanexpressioncanbeusedonlyasan expression statement (in statement chapter), because every other context in which anexpressioncanappearrequirestheexpressiontodenotesomething.

    Ifanexpressiondenotesavariable,andavalueisrequiredforuseinfurtherevaluation,thenthevalueofthatvariableisused.Inthiscontext,iftheexpressiondenotesavariableoravalue,we

    int a = 1; int b; b = a + 1; /* returns variable */

    int foo (int a){ return a + 1; } foo(3); /*returns a value*/

    int x = 7; void increase (int a) { x = x + a; } increase(2); /* returns nothing */

  • 12

    mayspeaksimplyofthevalueoftheexpression.Inthisway,wemaysayeachexpressiondenotesavalueinacertaintype.

    3.4.2TypeofanExpressionForanexpressionthatdenotestoavariable,thevaluestoredinavariableisalwayscompatiblewiththetypeofthevariable.Inotherwords,thevalueofanexpressionwhosetypeisTisalwayssuitableforassignmenttoavariableoftypeT.

    The rules for determining the type of an expression that denotes to a value are explainedseparatelybelowforeachkindofexpression.Includingarithmeticoperations,relationoperations,bitwise/conditionaloperations,assignment.

    3.4.3EvaluationOrder

    Livaguaranteesthattheoperandsofoperatorsareevaluatedinaspecificevaluationorder,namely,fromlefttoright.

    3.4.3.1Left-HandOperandFirst

    Theleft-handoperandofabinaryoperatorisfullyevaluatedbeforeanypartoftheright-handoperandisevaluated.

    3.4.3.2EvaluateOperandsbeforeOperation

    Livaguaranteesthateveryoperandofanoperator(excepttheconditionaloperators&,|)isfullyevaluatedbeforeanypartoftheoperationitselfisperformed.

    Forexample,inanassignmentexpression,theassignmentwillnotbeevaluateduntiltherighthandoperands(ifitisanotherexpression)isevaluated.

    3.4.3.3EvaluationRespectsParenthesesandPrecedence

    Liva respects the order of evaluation indicated explicitly by parentheses and implicitly byoperatorprecedence.

    3.4.4LexicalLiterals

    Aliteraldenotesafixed,unchangingvalue.Thiskindofexpressioncouldbeevaluatedwithout

  • 13

    beingbrokenintosmallexpressions.

    Thetypeofaliteralisdeterminedhasbeendefinedpreviously.Evaluationofalexicalliteralalwayscompletesnormally.

    3.4.5TheArithmeticOperationsTheoperators+,-,*,/,and%arecalledthearithmeticoperators.Anexpressionconcatenatedby an arithmetic operator is called an arithmetic expression. The value of an arithmeticexpressionisnumeric(intordouble,dependsontheoperands,definedpreviously).Theyhaveprecedenceoftwolevel:*,/and%arehigherthan+and-.Theyaresyntacticallyleft-associative(they group left-to-right). The type of the arithmetic expression is the promoted type of itsoperands.

    Thetypeofeachoftheoperandsofarithmeticoperatorsmustbeatypethatisconvertibletoaprimitivenumeric type,oracompile-timeerroroccurs.Forexample:adding twoobjectsofauser-definedclasswith“+”isprohibited.

    + Adds values on either side of the operator

    - Subtracts right hand operand from left hand operand

    * Multiplies values on either side of the operator

    / Divides left hand operand by right hand operand

    % Divides left hand operand by right hand operand and returns remainder

    3.4.6TheRelationalOperationsThevalueofanequalityexpressionisalwaysboolean.Theequalityoperatorsmaybeusedtocomparetwooperandsthatareconvertibletonumericinttype,ortwooperandsoftypeboolean.Livadoesnotsupportcharactercomparison.Allothercasesresultinacompile-timeerror.

    == Checks if the values of two operands are equal or not, if values are equal then condition becomes true.

    != Checks if the values of two operands are equal or not, if values are not equal then condition becomes true.

    > Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true.

  • 14

    3.4.7TheBitwiseandConditionalOperations:UnlikeJava,Livauses&,|,^,~forbothbitwiseandconditionaloperations.Thatdependsontheoperands.TheoperandsofaBitwise/ConditionalOperationshouldbothbeintorboolean.

    & Binary AND if both operands are int type / Logic AND if both operands are boolean type

    | Binary OR if both operands are int type / Logic OR if both operands are boolean type

    ^ Binary XOR if both operands are int type / Logic XOR if both operands are boolean type

    ~ Binary Complement if both operands are int type / Logic INVERT if both operands are boolean type

    3.4.8MethodInvocationExpressionsAmethod/function invocation expression is used to invoke an instancemethod (explanationabout instanceandmethodare intheclasssection).Theresulttypeofthechosenmethod isdeterminedasfollows:Ifthechosenmethod/functionisdeclaredwithareturntypeofvoid,thentheresultisvoid.Otherwise,theresulttypeisthemethod/function'sdeclaredreturntype.

    3.4.9ArrayAccessExpressionsAnarrayaccessexpressioncontainstwosubexpressions,thearrayreferenceexpression(beforetheleftbracket)andtheindexexpression(withinthebrackets).

    Notethatthearrayreferenceexpressionmaybeanameoranyprimaryexpressionthatisnotan

    < Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true.

    >= Checks if the value of left operand is greater than or equal to (no less than) the value of right operand, if yes then condition becomes true.

  • 15

    arraycreationexpression.Thetypeofthearrayreferenceexpressionmustbeanarraytype.Fortheindexexpression,thepromotedtypemustbeint,oracompile-timeerroroccurs.

    TheresultofanarrayaccessexpressionisavariableoftypeToranobject,namelythevariableortheobjectwithinthearrayselectedbythevalueoftheindexexpression.

    3.4.10AssignmentInLiva,theonlyassignmentoperatoris“=”.

    Theresultofthefirstoperandofanassignmentoperatormustbeavariable.Thisoperandmaybeanamedvariable,suchasalocalvariableorafieldofthecurrentobjectorclass,oritmaybeacomputedvariable,ascanresultfromafieldaccessoranarrayaccess(definedpreviously).

    3.5Statements Astatementformsacompleteunitofexecution.Allexpressionsofstatementsareexplainedinthefollowing.Exceptasindicated,statementsareexecutedinsequence.3.5.1ExpressionStatementsMoststatementsareexpressionstatementsandexpressionstatementsareusuallyassignmentsorfunctioncalls.Afunctioncallisacalltoafunctionalongwithitsformalarguments

    3.5.2DeclarationStatements

    /* Object creation expressions */ class Student e1 = new Student (); /* Assignment expressions */ c = 8933.234;

    int a; a = 1; /* variable assignment */ class foo { int value; constructor(int x) { this.value = x /* class field assignment */ } } class foo test = new foo (2); test.value = 3; /* object propertiesassignment*/

  • 16

    Adeclarationstatementdeclaresavariablebyspecifyingitsdatatypeandname.Italsocouldinitializethevariableduringthedeclaring.

    3.5.3ControlFlowStatements 3.5.3.1If-thenandIf-then-elseTherearetwoformsofconditionalstatements.For the first If-thencase, theconditionalexpression that isevaluated isenclosed inbalancedparentheses. The sectionof code that is conditionally executed is specified as a sequenceofstatementsenclosedinbalancedbraces.Iftheconditionalexpressionevaluatestofalse,controljumpstotheendoftheif-thenstatement.

    InthesecondIf-then-elsecase,thesecondsub-statementisexecutediftheexpressionisfalse.Inliva,forasinglestatement,thebracketsareoptional.

    Thefollowingexampleshowshowtouseif-thenelsestatement:

    /* declare a variable with data type and name */ char a; int b =10; float c; int [] array1 = new int [10] ; float n= 3.5; boolean isMatch = false;

    if (expression) { statement1 statement2 ...

    }

    if (expression) { statement1

    } else { Statement2

    }

  • 17

    3.5.3.2Looping:for The‘for’conditionwillalsoruninaloopsolongastheconditionspecifiedinthe‘for’statementistrue.The‘for’statementhasthefollowingformat:

    Thefirstexpressionspecifiesinitializationfortheloopanditisexecutedonceatthebeginningofthe'for'statement(livacouldnotacceptastatementforexpression1suchasinti=0);thesecondspecifies aBooleanexpression,madebeforeeach iteration, such that the loop is terminatedwhen the expression becomes false; the third expression specifies an operation which isperformedaftereachiteration.Thefollowingexampleusesa‘for’statementtoprintthenumbersfrom0to10:

    3.5.3.3Looping:whileThe‘while’statementhastheform:

    The‘while’statementwillbeexecutedinaloopaslongasthespecifiedconditioninthewhilestatementistrue.Theexpressionmusthavetypeboolean,oracompile-timeerroroccurs.

    for (expression1; expression2; expression 3) { statement

    }

    int num; for (num=0; num < 11; num ++) { print(num); }

    while(expression) { statement

    }

    if (true){ print(42); print (100);

    } else { print(8);

    }

  • 18

    • Ifthevalueforexpressionistrue,thenthecontainedstatementisexecuted

    • Ifexecutionofthestatementcompletesnormally,thentheentire‘while’statementisexecutedagain,beginningbyre-evaluatingtheexpression.

    • Ifthevalueoftheexpressionisfalse,nofurtheractionistakenandthe‘while’statementcompletesnormally.

    Thefollowingexampleshowshowtouse‘while’statement:

    3.5.3.4Return A‘return’returnstoitscallerbymeansofthe‘return’statement,whichhasoneoftheforms:

    Inthefirstcasenovalueisreturnedwhenamethodisdeclaredvoid.Forthefirstcase,theuserscouldspecifynoreturnstatementforsimplification.Inthesecondcase,simplyputthevalue(oran expression that calculates the value) after the return Keyword, then the value of theexpressionisreturnedtothecallerofthe‘return’. 3.5.4MethodCreationandMethodCall Theusercouldwritetheuser-definedmethods.

    • returnType: Methodmayreturnavalue. • nameOfMethod: Thisisthemethodname.Themethodsignatureconsistsofthemethod

    nameandtheparameterlist.

    return; return(expression);

    returnType nameOfMethod (Parameter List) { /*method body*/ }

    int i=10; while (i > 0) { print(i); i = i - 1; }

  • 19

    • Parameter List: The list of parameters, it is the type, order, and number ofparametersofamethod.Theseareoptional,methodmaycontainzeroparameters.Ausualformatfortheparameterlistis(dataTypeId,dataTypeId…,dataTypeId)

    • method body: Themethodbodydefineswhatthemethoddoeswithstatements. Forusingamethod,itshouldbecalled.Therearetwowaysinwhichamethodisreturnedi.e.methodreturnsavalueorreturningnothing(noreturnvalue).Themethodshouldbedefinedinaclass.Following is the example to demonstrate how to define amethod and how to call itwith areturnedvalueinaclass(refertosection3.6):

    3.5.5PrinttoConsole Theprint()functiontakesoneormoreparametersandprintsthemonebyonetostandardoutput.Theparametertypemaybestring,number.Itisinthefollowingform:

    class myclass{ int calc (int x, int y){ int z; z = x + y; return (z); } } class test { void main(){ int x = 9; float y = 6.0; float z; class myclass obj = new myclass(); z = obj.calc(x, y); print ("z=", z); } }

    print (parameters);

  • 20

    Hereisanexampletoacceptanintandprinttheinttotheconsole.

    Anotherexampletoacceptastringandprintthestringtotheconsole:

    3.5.6EmptyStatement Anemptystatementdoesnothingandhasthefollowingform:

    3.6ClassesClassesandobjectsarehighlyrelated.Arealworldobjecthasstatesandbehaviors.Forinstance,adoghasstates—name,breed,coloraswellasbehaviors—barking,eating.AnobjectinLivaalsohasstates—storedinfieldsandbehaviors—shownviamethods.Fieldsarelocalvariablesstoredinsideaclassandmethodsarefunctionsthatmaybeinvokedbyinstancesofthatclass.Soclassbodiesconsistoffieldsandmethods.Actually,thereisaspecialkindofmethodscalledconstructorswhichwillbediscussedinfollowingsections.Inaword,aclasscanbedefinedasatemplatethatdescribesthestatesandbehaviorsthatobjectsofitstypesupport.3.6.1ClassDeclarationsAclassdeclarationdefinesanewreferencetypeandhowitisimplemented.Abodyofaclassdeclarationcontainsfielddeclarationsandmethoddeclarations.Followingisanexampleofhowto define a class.Use the keyword “class” to indicate the start of a class declaration. In thisexample, “myclass” is the class name. It has two fields, one is an integer and the other is acharacter.Onemethod“fuction1”isdefineanditsimplyreturnsinteger1.3.6.2ObjectInstantiation

    class myclass { int field1; char field2; int function1(){ return (1); } }

    print (1);

    print (“CS4115 is fun!”)

    ;

  • 21

    The ‘new’keyword isusedto instantiateanewobjectbyallocatingmemoryfor it.The ‘new’requiresasingleargument:aconstructormethodfortheobjecttobecreated.Theconstructormethodisresponsibleforinitializingthenewobject.InLiva,thenameofconstructormethodforoneclassisdefinedas“constructor”.Theusercoulddefineaconstructorintheclass.livawouldcreateadefaultconstructorfortheclassiftheusersdonotexplicitlydefineaconstructorforaclass.Itisessentiallyanon-parameterizedconstructorwithoutanyarguments.Thefunctionofdefaultconstructoristocallthesuperclassconstructorandinitializeallinstancevariables.Whenthekeyword‘this’isused,itisreplacedbyaninstanceofthecontainingobjectatruntime. Thefollowingexampleshowshowtodefineaconstructormethodandinitializeanewobject:

    3.6.3InheritanceInheritanceisthatasubclassacquiresallthebehaviorsandpropertiesofasuperclass.Asubclassinheritsfieldsandmethodsfromitsparentclass.Thekeyword“extends”isusedtoindicatearelationshipbetweenasubclassandaparentclasslikethefollowingdeclaration.

    class subclass extends myclass { }

    /* User defined constructor*/ class myclass{ int a; constructor(int x){ this.a = x; } } class test { void main(){ class myclass obj = new myclass(10); print ("a=", obj.a); } }

  • 22

    Asubclassmayoverridethemethodsofitsparentclass.Ifamethodisoverridden,aninstanceofthesubclasscanonlyaccessthenewversionbutnottheoriginalmethodfromthesuperclass.

    Chapter 4 Project Plan 4.1PlanOurgroupmembersworkedcollaborativelyonGithub.Atthebeginning,westudiedthecodeoftheMicroClangugetogetmoreunderstandingaboutcompilerdesign.WehavemetourTAeveryweek to discuss our project and ask questions. After we got the “Hello Word” programsuccessfullycompiled,weworkedtogethertoaddmorefeaturesandfixbugs.Finally,inthelastweek,weaskedourTAaboutthepriorityofthefeaturesweplannedtoaddandimplementedsomeofthemwithhighpriorities.4.2Timeline

    July6th-11th Brainstormforlanguagedesignandtheproposal

    July11th–20th Determinelanguagesyntaxandscope;WriteLanguageReferenceManual

    July20th–July25th ScannerandParserJuly25th–August1st Expressions,Printfunctionandmainfunction

    August1st “HelloWorld!”August1st–August

    8thAddobject-orientedfeaturesandarray.Fixbugs

    class myclass{ int calc (int x, int y){ int z; z = x + y; return (z); } } class subclass extends myclass{ int calc (int x, int y){ int z; z = x + y + 1; return (z); } }

  • 23

    August8th-August11th

    Reportandpresentation.

    4.3RolesandResponsibilities.Inourteam,theroleofeachmemberwasquiteflexible.Weworkedtogetherveryoftencodingandfixingbugs.Wehavesolvedmanyproblemstogetherthesedays.ZihanandShanqimainlyconcentratedonimplementingthecodegenerator.JiafeiandYananfocusedonsemanticcheck.Katejoinedusfromthemiddleofourprojectandshedidsometestinganddocumentwork.4.4SoftwareEnvironmentUbuntu16.04–AllourteammembersworkonUbuntu16.4,thelatestversiontoavoidunnecessaryenvironmentconflict.OurUbuntuarepoweredbyPD11andVMware12.OSX–Meanwhile,wealsotryourlanguageonOSXtoensurethatLIVAisportable.LLVM3.6-AllourteammembersworkwithLLVM3.6Github–WeworkonthesamebranchinourGithubrepository.4.5ProjectProlog

    ThecommitcurvefromJuly3toAug11.Itshowsourworkdistributedevenlyduringthe30-dayperiod.AllourteammembersinvolvedheavilyinthedevelopmentofLIVA.

  • 24

    Chapter 5 Architecture Design 5.1Overview

    Figure5.1Overviewofcompilerarchitecturedesign

    ThecompilerarchitecturaldesignofLivaisshowninFigure5.1.Overall,Livafollowsatraditionalcompiler architecture designwith a lexical scanner and parser at the front end, followed bygenerationofaSemanticallyCheckedandTypedAbstractSyntaxTree(SAST)fromanabstractsyntaxtree(AST)andfinallyLLVMIRcodegeneration.Wehaveatotalof5moduleswhicharecodegen.ml,liva.ml,semant.ml,parser.mly,scanner.mlland2interfaceswhichareast.mlandsast.ml.5.2ThescannerAsthestartofthefrontend,scannerreadsasourcefileandconvertitintotokens,andatthesametimeitcheckswhethereachtokensisvalid,ifnot,itwillreporttheillegalcharacter.Besides,it is also responsible for ignoring white space and comments which are not useful for Livaprogram.5.3TheParserThetokenspassedbythescannerare interpretedby theparseraccordingto theprecedencerulesofLivalanguageandconstructsanabstractsyntaxtreebasedonthedefinitionsprovidedandthe inputtokensareconstructed.Theparser’smaingoal is toorganizethetokensoftheprogram intoclassdeclarations.Thetop levelof theabstractsyntax tree isastructurecalledProgramwhichcontainsallclasses.Thefields,constructorsandmethodsaredeclaredwithintheclasses.SpecifictothemethoddeclarationsrecordisthecreationofanASToffunctionsfromgroupsofstatements,statementsevaluatingtheresultsofexpressions,andexpressionsformedfromoperationsandassignmentsofvariables,referencesandconstants.TheParserproducestheabstractsyntaxtree(AST)whichisshowninFigure5.1.

  • 25

    Figure5.2ASTprogramrepresentation.

    5.4TheSemanticCheckerTherearefourkindsofworkasemanticcheckerisresponsiblefor.Tobeginwith,itaddsreservedfunctionsasapartoftheSASTshowninfigure5.3,andthesereservedfunctionscanalsohelptocheckwhetherthereareanyfunctionsusethesamenameasreservedoneswhichisnotallowedinLiva.Next,semanticcheckerdosomeworkconcerningstatisticsemanticchecking.Itcheckswhetherthesourcecodeissemanticallycorrectfromvariousaspectsincludingwhetherthereare duplicated fields or methods in one class, whether there are duplicated classes in oneprogramandaddsdefaultconstructorifthereisn’tuser-definedconstructorinoneclass.Thirdly,onthebasisofthefirsttwosemanticcheckerdealswithinheritance.Semanticcheckerfindsallthe inheritance relationship by looking through all the classes, if there is a inheritancerelationshipbetweentwoclasses,semanticcheckerwilladdthefieldsandthemethodsofsuperclasstosubclass,butitthesubclassdeclaresfieldsormethodswhichsharethesamenameasthose of super class, subclass will override those fields andmethods of super class. Finally,semanticcheckerconvertsitsinput,AST,toSASTwhichishelpfulforcodegeneratortogenerateLLVMIRcode.Semanticcheckerseparatesthemethodsfromclasses,separatesmainmethodwhichistheentranceofLivaprogramfrommethodsandaddtypestoallthestatementsandexpressions, in themeanwhile, italsodosomework relatedwithstatistic semanticchecking,includingwhethernamesoridentifiersaredefinedbeforetheyarereferredto,whethernamesoridentifiersareusedcorrectly,whethertypesareconsistentandsoontomakeitassmoothaspossibleforcodegeneratortogeneratecode.

  • 26

    Figure5.3SASTrepresentation.

    5.5TheCodeGenerator ThemainfunctionofthecompileristoconverttheabstractsyntaxtreeintoLLVMIR.Afterthesemanticabstractsyntaxtreeisgenerated,thesemanticcheckersendsittothecodegeneratorwhichconstructtheLLVMIRfilewhichcontainsthefinalinstructionsfortheprogram.Thiscodegeneration iswrittenusingtheOCamlLLVMlibrary,whichusesOCamlfunctionstoproduce the desired LLVM code with the static variables used during codegeneration.Codegen.the_moduleisthetop-levelstructurethattheLLVMIRusestocontaincodeand it contains all of the functions and global variables in a chunk of code.TheCodegen.builderobjectisaobjectthatkeepstrackofthecurrentplacetoinsertinstructionsandhasmethods to createnew instructions. TheCodegen.named_valuesmap keeps trackofwhichvaluesaredefinedinthecurrentscopeandwhattheirLLVMrepresentationis.Afterallofaboveissetup,thecodegeneratoriteratesthroughtheentiresemanticabstractsyntaxtreeandproducesthenecessaryLLVMcodeforeachfunction,statement,andexpression.

    Chapter 6 Test Plan AllthetestcasesusedtotestLivaareputintoafoldernamedtests.Thetestcaseswhichconsistofunittests,integrationtestsaredesignedtotestallthefeaturesofLiva,frombothpositivewayand negative way. All these various testing methods are used to create a robust testingenvironmentforLivalanguage.6.1Reasonforchoosingtestcases

  • 27

    Allthetestswereaddedasnewlanguagefeatureswereadded,therefore,thelanguagefeaturesdecidedthetestcaseswepickedout toa largeextent,andmostof these testsareaimedattestingeveryaspectofLiva. 6.2UnittestingUnittestingwasusedtocheckwhethersmallpiecesofourlanguagecouldbehaveasdefined.Thetestscanbedividedintotwotypes:testsaremeanttopass,testsaremeanttofail,therebyutilizingpositiveandnegativetesting.Negativetestingensuresthatinvalidinputisnotaccepted,i.e.Livaisabletoproperlyrejectinvalidinput,whilepositivetestingontheotherhandallowsustoassesswhetherLivaisabletobehaveandworkouttheresultasdefined. 6.3IntegrationtestingOncesmallertestswereverifiedtopass,theywouldbeintegratedintolargerprograms,soastoensurewhetherLivacanmanagetobehaveproperlyinmorecomplexprogram.Theseintegratedtestsarethebasisofourfinalinterestingprogram.6.4AutomationAutomationoftestingbecomesmoreandmorenecessaryastheprojectmovesforward,anditisanextremelyusefultoolfordevelopingourlanguage.Automationallowsustomakesurethatnewaddedlanguagefeatureswouldnotobstructotherfeatureswhichhavepassedthetests.WecreatedanautomatedregressiontestsuitelargelyborrowedfromtheMicroCCompiler.Thetestcasesmeanttopassarewrittenoutusingthenotation ‘test-.liva’andthecorrespondingoutputas‘test-.out’,whilethecorrespondingoutputoftestcasesmeattofailas‘test-.err’.Thetestscriptisexecutedwiththe./testall.shcommandwhichwillthendisplayalistofteststhatpass,fail,orproduceaprintedoutputthatdiffersfromthedesiredprintedoutput.6.5Representativesourceprograms test-inheritance2.liva class calculator { int add(int x, int y){ int z = x + y; return(z); } } class my_calculator extends calculator{ }

  • 28

    class test { void main(){ int x; int y; int z; x = 66; y = 98; class my_calculator obj = new my_calculator(); z = obj.add(x,y); print ("z=",z); } } test-inheritance2.ll ; ModuleID = 'Liva' %test = type %my_calculator = type %calculator = type @tmp = private unnamed_addr constant [3 x i8] c"z=\00" @tmp.1 = private unnamed_addr constant [5 x i8] c"%s%d\00" declare i32 @printf(i8*, ...) declare i8* @malloc(i32) define i64* @lookup(i32 %c_index, i32 %f_index) { entry: %tmp = alloca i64**, i32 3 %tmp1 = alloca i64*, i32 0 %tmp2 = getelementptr i64**, i64*** %tmp, i32 2 store i64** %tmp1, i64*** %tmp2 %tmp3 = alloca i64* %tmp4 = getelementptr i64*, i64** %tmp3, i32 0 store i64* bitcast (i32 (%my_calculator*, i32, i32)* @my_calculator.add to i64*), i64** %tmp4 %tmp5 = getelementptr i64**, i64*** %tmp, i32 1 store i64** %tmp3, i64*** %tmp5 %tmp6 = alloca i64* %tmp7 = getelementptr i64*, i64** %tmp6, i32 0 store i64* bitcast (i32 (%calculator*, i32, i32)* @calculator.add to i64*), i64** %tmp7 %tmp8 = getelementptr i64**, i64*** %tmp, i32 0 store i64** %tmp6, i64*** %tmp8 %tmp9 = getelementptr i64**, i64*** %tmp, i32 %c_index %tmp10 = load i64**, i64*** %tmp9 %tmp11 = getelementptr i64*, i64** %tmp10, i32 %f_index %tmp12 = load i64*, i64** %tmp11 ret i64* %tmp12

  • 29

    } define %test* @test.constructor() { entry: %this = alloca %test %tmp = call i8* @malloc(i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32)) %tmp1 = bitcast i8* %tmp to %test* %tmp2 = load %test, %test* %tmp1 store %test %tmp2, %test* %this %.key = getelementptr inbounds %test, %test* %this, i32 0, i32 0 store i32 2, i32* %.key ret %test* %this } define i32 @my_calculator.add(%my_calculator* %this, i32 %x, i32 %y) { entry: %z = alloca i32 %addtmp = add i32 %x, %y store i32 %addtmp, i32* %z %z1 = load i32, i32* %z ret i32 %z1 } define %my_calculator* @my_calculator.constructor() { entry: %this = alloca %my_calculator %tmp = call i8* @malloc(i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32)) %tmp1 = bitcast i8* %tmp to %my_calculator* %tmp2 = load %my_calculator, %my_calculator* %tmp1 store %my_calculator %tmp2, %my_calculator* %this %.key = getelementptr inbounds %my_calculator, %my_calculator* %this, i32 0, i32 0 store i32 1, i32* %.key ret %my_calculator* %this } define i32 @calculator.add(%calculator* %this, i32 %x, i32 %y) { entry: %z = alloca i32 %addtmp = add i32 %x, %y store i32 %addtmp, i32* %z %z1 = load i32, i32* %z ret i32 %z1 } define %calculator* @calculator.constructor() { entry: %this = alloca %calculator %tmp = call i8* @malloc(i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32)) %tmp1 = bitcast i8* %tmp to %calculator*

  • 30

    %tmp2 = load %calculator, %calculator* %tmp1 store %calculator %tmp2, %calculator* %this %.key = getelementptr inbounds %calculator, %calculator* %this, i32 0, i32 0 store i32 0, i32* %.key ret %calculator* %this } define i32 @main() { entry: %this = alloca %test %tmp = call i8* @malloc(i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32)) %tmp1 = bitcast i8* %tmp to %test* %tmp2 = load %test, %test* %tmp1 store %test %tmp2, %test* %this %.key = getelementptr inbounds %test, %test* %this, i32 0, i32 0 store i32 2, i32* %.key %x = alloca i32 %y = alloca i32 %z = alloca i32 store i32 66, i32* %x store i32 98, i32* %y %obj = alloca %my_calculator %tmp3 = call %my_calculator* @my_calculator.constructor() %tmp4 = load %my_calculator, %my_calculator* %tmp3 store %my_calculator %tmp4, %my_calculator* %obj %cindex = getelementptr inbounds %my_calculator, %my_calculator* %obj, i32 0, i32 0 %cindex5 = load i32, i32* %cindex %fptr = call i64* @lookup(i32 %cindex5, i32 0) %my_calculator.add = bitcast i64* %fptr to i32 (%my_calculator*, i32, i32)* %x6 = load i32, i32* %x %y7 = load i32, i32* %y %tmp8 = call i32 %my_calculator.add(%my_calculator* %obj, i32 %x6, i32 %y7) store i32 %tmp8, i32* %z %z9 = load i32, i32* %z %tmp10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @tmp.1, i32 0, i32 0), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @tmp, i32 0, i32 0), i32 %z9) ret i32 0 } 2. test-while_for_nest.liva class test { void main(){ int i = 1; int j; while(i < 10) { j = 11; for(j = 11; j < 13; j = j + 1)

  • 31

    print("i = ", i, " ", "j = ", j, "\n"); i = i + 1; } print("\n\n"); for(i = 1; i < 10; i = i + 1) { j = 11; while(j < 13) { print("i = ", i, " ", "j = ", j, "\n"); j = j + 1; } } } } test-while_for_nest.ll ; ModuleID = 'Liva' %test = type @tmp = private unnamed_addr constant [5 x i8] c"i = \00" @tmp.1 = private unnamed_addr constant [2 x i8] c" \00" @tmp.2 = private unnamed_addr constant [5 x i8] c"j = \00" @tmp.3 = private unnamed_addr constant [2 x i8] c"\0A\00" @tmp.4 = private unnamed_addr constant [13 x i8] c"%s%d%s%s%d%s\00" @tmp.5 = private unnamed_addr constant [3 x i8] c"\0A\0A\00" @tmp.6 = private unnamed_addr constant [3 x i8] c"%s\00" @tmp.7 = private unnamed_addr constant [5 x i8] c"i = \00" @tmp.8 = private unnamed_addr constant [2 x i8] c" \00" @tmp.9 = private unnamed_addr constant [5 x i8] c"j = \00" @tmp.10 = private unnamed_addr constant [2 x i8] c"\0A\00" @tmp.11 = private unnamed_addr constant [13 x i8] c"%s%d%s%s%d%s\00" declare i32 @printf(i8*, ...) declare i8* @malloc(i32) define i64* @lookup(i32 %c_index, i32 %f_index) { entry: %tmp = alloca i64** %tmp1 = alloca i64*, i32 0 %tmp2 = getelementptr i64**, i64*** %tmp, i32 0 store i64** %tmp1, i64*** %tmp2 ret i64* null } define %test* @test.constructor() { entry:

  • 32

    %this = alloca %test %tmp = call i8* @malloc(i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32)) %tmp1 = bitcast i8* %tmp to %test* %tmp2 = load %test, %test* %tmp1 store %test %tmp2, %test* %this %.key = getelementptr inbounds %test, %test* %this, i32 0, i32 0 store i32 0, i32* %.key ret %test* %this } define i32 @main() { entry: %this = alloca %test %tmp = call i8* @malloc(i32 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i32)) %tmp1 = bitcast i8* %tmp to %test* %tmp2 = load %test, %test* %tmp1 store %test %tmp2, %test* %this %.key = getelementptr inbounds %test, %test* %this, i32 0, i32 0 store i32 0, i32* %.key %i = alloca i32 store i32 1, i32* %i %j = alloca i32 br label %cond loop: ; preds = %cond store i32 11, i32* %j store i32 11, i32* %j br label %cond5 loop3: ; preds = %cond5 %i7 = load i32, i32* %i %j8 = load i32, i32* %j %tmp9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @tmp.4, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @tmp, i32 0, i32 0), i32 %i7, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tmp.1, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @tmp.2, i32 0, i32 0), i32 %j8, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tmp.3, i32 0, i32 0)) br label %step4 step4: ; preds = %loop3 %j10 = load i32, i32* %j %addtmp = add i32 %j10, 1 store i32 %addtmp, i32* %j br label %cond5 cond5: ; preds = %step4, %loop %j11 = load i32, i32* %j %lesstmp = icmp slt i32 %j11, 13 br i1 %lesstmp, label %loop3, label %afterloop6

  • 33

    afterloop6: ; preds = %cond5 %i12 = load i32, i32* %i %addtmp13 = add i32 %i12, 1 store i32 %addtmp13, i32* %i br label %step step: ; preds = %afterloop6 br label %cond cond: ; preds = %step, %entry %i14 = load i32, i32* %i %lesstmp15 = icmp slt i32 %i14, 10 br i1 %lesstmp15, label %loop, label %afterloop afterloop: ; preds = %cond %tmp16 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @tmp.6, i32 0, i32 0), i8* getelementptr inbounds ([3 x i8], [3 x i8]* @tmp.5, i32 0, i32 0)) store i32 1, i32* %i br label %cond19 loop17: ; preds = %cond19 store i32 11, i32* %j br label %cond23 loop21: ; preds = %cond23 %i25 = load i32, i32* %i %j26 = load i32, i32* %j %tmp27 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @tmp.11, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @tmp.7, i32 0, i32 0), i32 %i25, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tmp.8, i32 0, i32 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @tmp.9, i32 0, i32 0), i32 %j26, i8* getelementptr inbounds ([2 x i8], [2 x i8]* @tmp.10, i32 0, i32 0)) %j28 = load i32, i32* %j %addtmp29 = add i32 %j28, 1 store i32 %addtmp29, i32* %j br label %step22 step22: ; preds = %loop21 br label %cond23 cond23: ; preds = %step22, %loop17 %j30 = load i32, i32* %j %lesstmp31 = icmp slt i32 %j30, 13 br i1 %lesstmp31, label %loop21, label %afterloop24 afterloop24: ; preds = %cond23 br label %step18

  • 34

    step18: ; preds = %afterloop24 %i32 = load i32, i32* %i %addtmp33 = add i32 %i32, 1 store i32 %addtmp33, i32* %i br label %cond19 cond19: ; preds = %step18, %afterloop %i34 = load i32, i32* %i %lesstmp35 = icmp slt i32 %i34, 10 br i1 %lesstmp35, label %loop17, label %afterloop20 afterloop20: ; preds = %cond19 ret i32 0 } Test suites fail-add.liva: class arith { void main() { int i; i = "1" + 1; print(i); } } ------------------------------------------------------------------------------------------------------ fail-array_access.liva: class test { void main() { char b = 'a'; float[] a = new float[10]; print(a[b]); } } ------------------------------------------------------------------------------------------------------ fail-array_access2.liva: class test { void main() { float[] a = new float[10]; print(a[1][1]); } } ------------------------------------------------------------------------------------------------------ fail-array_init.liva: class test { void main() { float[] a = new float[10.0];

  • 35

    } } ------------------------------------------------------------------------------------------------------ fail-diff.liva: class arith { void main() { int i; i = "1" - 1; print(i); } } ------------------------------------------------------------------------------------------------------ fail-div.liva: class arith { void main() { int i; i = "4" / 2; print(i); } } ------------------------------------------------------------------------------------------------------ fail-equal1.liva: class test { void main(){ float i = 1.0; if (i == 1.0) print(42); else print(8); } } ------------------------------------------------------------------------------------------------------ fail-equal2.liva: class test { void main(){ float i = "123"; if (i == true) print(42); else print(8); } } ------------------------------------------------------------------------------------------------------ fail-for1.liva: class test { void main(){

  • 36

    int i; for (i = 0 ; i = 10 ; i = i + 1) { print(i); } } } ------------------------------------------------------------------------------------------------------ fail-function.liva: class myclass{ int calc (int x, int y){ int z; z = x + y; return (z); } } class test { void main(){ int x = 9; int y = 6; int z; class myclass obj = new myclass(); z = obj.ca_lc(x, y); print ("z=",z); } }

  • 37

    ------------------------------------------------------------------------------------------------------ fail-function2.liva: class myclass{ int calc (int x, int y){ int z; z = x + y; return (z); } } class test { void main(){ int x = 9; int y = 6; int z; class myclass obj = new myclass(); z = obj.calc(x, x, y); print ("z=",z); } } ------------------------------------------------------------------------------------------------------ fail-function3.liva: class myclass{ int calc (int x, int y){

  • 38

    int z; z = x + y; return (z); } } class test { void main(){ int x = 9; float y = 6.0; float z; class myclass obj = new myclass(); z = obj.calc(x, y); print ("z=",z); } } ------------------------------------------------------------------------------------------------------ fail-hello.liva: class test { print ("Hello World!"); void main(){ } } ------------------------------------------------------------------------------------------------------ fail-hello2.liva: class test { void main(){ int a ; int b ; a=1.1; b=3; print ("multiple ", "params!", "\n", a, "\n" ,b, "\n"); } } ------------------------------------------------------------------------------------------------------ fail-if1.liva: class test { void main(){

  • 39

    if ("123") print(42); } } ------------------------------------------------------------------------------------------------------ fail-mod.liva: class arith { void main() { int i; i = "4" % 3; print(i); } } ------------------------------------------------------------------------------------------------------ fail-mul.liva: class arith { void main() { int i; i = "15" * 5; print(i); } } ------------------------------------------------------------------------------------------------------ fail-not.liva: class test { void main(){ int i = 1; boolean j; j = !(i + 1); } } ------------------------------------------------------------------------------------------------------ fail-obj_access.liva: class test { void main() { int a; a.amethod; } } ------------------------------------------------------------------------------------------------------ fail-obj_access2.liva: class test { void main() { int a; (1+1).amethod; }

  • 40

    } ------------------------------------------------------------------------------------------------------ fail-obj_access3.liva: class myclass{ int a; constructor(int x){ this.a = x; } } class test { void main(){ class myclass obj = new myclass(10); print ("b=",obj.b); } } ------------------------------------------------------------------------------------------------------ fail-sub.liva: class test { void main(){ int j; j = -(true); print(j); } } ------------------------------------------------------------------------------------------------------ fail-while1.liva: class test { void main() { int i; i = 5; while (i = 1) { print(i); i = i - 1; } print(42); } } ------------------------------------------------------------------------------------------------------ test-add.liva: class arith { void main() { int i; i = 1 + 1; print(i); } }

  • 41

    ------------------------------------------------------------------------------------------------------ test-and.liva: class test { void main(){ int i = 1; int j = 3; if (i == 1 & j == 3) { print(i, " ", j, "\n"); } } } ------------------------------------------------------------------------------------------------------ test-arith.liva: class arith { void main() { int i; i = 1 + 3 * 4 % 7 - 4 / 2; print(i); } } ------------------------------------------------------------------------------------------------------ test-array.liva: class test { void main() { float[] a = new float[10]; int[] b = new int[10]; int i; a[0] = 1.0; b[0] = 1; for(i = 1; i < 10; i = i + 1) { a[i] = a[i - 1] + 1.0; b[i] = b[i - 1] + 1; } for(i = 0; i < 10; i = i + 1) print("a[",i,"]"," = ",a[i]," , ", "b[",i,"]"," = ",b[i], "\n"); } } ------------------------------------------------------------------------------------------------------ test-array_object.liva: class calculator{ int g; int addition(int x, int y){ this.g =9; int z; z = x + y; return(z); }

  • 42

    } class test { void main() { class calculator c = new calculator(); class calculator[] a = new class calculator[10]; a[0] = c; print(a[0].addition(1,1)); } } ------------------------------------------------------------------------------------------------------ test-comments.liva: class test { void main(){ float i = 1.111; /*HAHAHAHA /* print(i);*/ BOOOO!%$#$^%^&^%g)__*%^#@... */ print(i); } } ------------------------------------------------------------------------------------------------------ test-constructor.liva: class myclass{ int a; constructor(int x){ this.a = x; } } class test { void main(){ class myclass obj = new myclass(10); print ("a=",obj.a); } } ------------------------------------------------------------------------------------------------------

  • 43

    test-diff.liva: class arith { void main() { float i; i = 1.3 - 1.0; print(i); } } ------------------------------------------------------------------------------------------------------ test-div.liva: class arith { void main() { int i; i = 4 / 2; print(i); } } ------------------------------------------------------------------------------------------------------ test-equal.liva: class test { void main(){ int i = 1; if (i == 1) print(42); else print(8); } } ------------------------------------------------------------------------------------------------------ test-fib.liva: class test { int fib (int x){ int z; if (x

  • 44

    z = this.fib (x); print (z); } } ------------------------------------------------------------------------------------------------------ test-for1.liva: class test { void main(){ int i; for (i = 0 ; i < 10 ; i = i + 1) { print(i); } } } ------------------------------------------------------------------------------------------------------ test-for_nest.liva: class test { void main(){ int i; int j; for(i = 0; i < 10; i = i + 1) for(j = 11; j < 13; j = j + 1) print("i = ", i, " ", "j = ", j, "\n"); } } ------------------------------------------------------------------------------------------------------ test-function.liva:

  • 45

    class myclass{ int calc (int x, int y){ int z; z = x + y; return (z); } } class test { void main(){ int x; int y; int z; x = 9; y = 6; class myclass obj = new myclass(); z = obj.calc(x, y); print ("z=",z); } } ------------------------------------------------------------------------------------------------------ test-gcd.liva: class gcd { void main(){ int x; int y; int z; x = 66; y = 98; while(x != y){ if(x > y){ x = x - y; } else{ y = y - x;

  • 46

    } } print ("gcd=",x); } } ------------------------------------------------------------------------------------------------------ test-geq.liva: class test { void main(){ int i = 1; int j = 1; if (i >= j) print("yes"); else print("no"); } } ------------------------------------------------------------------------------------------------------ test-gt.liva: class test { void main(){ int i = 4; int j = 1; if (i > j) print(4); else print(8); } } ------------------------------------------------------------------------------------------------------ test-hello.liva: class test { void main(){ print ("Hello World!"); } } ------------------------------------------------------------------------------------------------------ test-hello2.liva:

  • 47

    class test { void main(){ int a ; int b ; a=1; b=3; print ("multiple ", "params!", "\n", a, "\n" ,b, "\n"); } } ------------------------------------------------------------------------------------------------------ test-if1.liva: class test { void main(){ print (100); if (true) print(42); else print(8); print(17); } } ------------------------------------------------------------------------------------------------------ test-if_nest.liva: class test { void main(){ int i = 1; int j = 3; if (true) { if(i == 1) { if(i < j) { print(j); } }

  • 48

    } } } ------------------------------------------------------------------------------------------------------ test-inheritance.liva: class myclass{ int a; constructor(int x){ this.a = x; } } class subclass extends myclass{ constructor(int x){ this.a = x; } } class test { void main(){ class subclass obj = new subclass(10); print ("a=",obj.a); } } ------------------------------------------------------------------------------------------------------ test-inheritance2.liva: class calculator { int add(int x, int y){ int z = x + y; return(z); } } class my_calculator extends calculator{ }

  • 49

    class test { void main(){ int x; int y; int z; x = 66; y = 98; class my_calculator obj = new my_calculator(); z = obj.add(x,y); print ("z=",z); } } ------------------------------------------------------------------------------------------------------ test-leq.liva: class test { void main(){ int i = 1; int j = 1; if (i

  • 50

    print(i); } } ------------------------------------------------------------------------------------------------------ test-mul.liva: class arith { void main() { int i; i = 15 * 5; print(i); } } ------------------------------------------------------------------------------------------------------ test-nequal.liva: class test { void main(){ int i = 3; if (i != 1) print(4); else print(8); } } ------------------------------------------------------------------------------------------------------ test-not.liva: class test { void main(){ int i = 1; int j = 3; if (!(i != 1)) { print("BOOO!"); } } } ------------------------------------------------------------------------------------------------------ test-obj.liva: class myclass{ } class test { void main(){ class myclass obj = new myclass(); print ("obj\n"); } }

  • 51

    ------------------------------------------------------------------------------------------------------ test-or.liva: class test { void main(){ int i = 1; int j = 3; if (i != 1 | j == 3) { print(i, " ", j, "\n"); } } } ------------------------------------------------------------------------------------------------------ test-override.liva: class myclass{ int a; int calc (int x, int y){ int z; z = x + y; return (z); } } class subclass extends myclass{ int calc (int x, int y){ int z; z = x - y; return (z); } } class test { void main(){ int x; int y; int z; x = 9; y = 6; class subclass obj = new subclass();

  • 52

    z = obj.calc(x, y); print ("z=",z); } } ------------------------------------------------------------------------------------------------------ test-sub.liva: class test { void main(){ int i = 3; int j; j = -(-(i) + i * i); print(j); } } ------------------------------------------------------------------------------------------------------ test-while1.liva: class test { void main() { int i; i = 5; while (i > 0) { print(i); i = i - 1; } print(42); } } ------------------------------------------------------------------------------------------------------ test-while_for_nest.liva: class test { void main(){ int i = 1; int j; while(i < 10) { j = 11; for(j = 11; j < 13; j = j + 1) print("i = ", i, " ", "j = ", j, "\n"); i = i + 1; }

  • 53

    print("\n\n"); for(i = 1; i < 10; i = i + 1) { j = 11; while(j < 13) { print("i = ", i, " ", "j = ", j, "\n"); j = j + 1; } } } }

    Chapter 7 Lessons Learned Shanqi:Startearlyanddonotsurrendertodifficultbugs.Thereisnotmuchonlinecommunitysupportsfor OCaml Llvm API. I found this website helpful https://llvm.moe/ocaml-3.7/Llvm.html .However,thisisnotenoughandyoumaywanttorefertorelatedpastprojectsforsomehelp.Atthebeginning,weallhatedOCamlandfoundnothingworth in it.Now, I thinkthat themostvaluablethingaboutOCamlisthepatternmatching.IcannotimagehowmanyswitchstatementswouldbeusedifwecodedthecompilerinJava.FirstthingtodoistomakesurethatyouunderstandthebasicfunctionsofthemakefileandtestshellinMicroC.Theyareusefulduringthedevelopmentprocess.MicroCisagreatexampleforbeginners.Afteryouunderstandit,youwillknowwhatisthebasicstepsofcompilingalanguage.Theparserfileandtheastfilearetwohighlyrelatedthings.Theyonlydoonething—reducetokensaccordingtotherulesinparsertoasinglerootelement.Inmostcases,wecalltheroot“program”.Semanticcheckandcodegeneratorarethemosttime-consumingparts.Alldifficultbugsappearhere.Someofyourgroupmembersmayfocusonsemanticcheckandothersoncodegenerator.Ocamlhasthemagic“letrec…”bindingwhichmakesthefollowingbindingsstartwith“andlet…”aconnectedblock.Agoodsoftwarearchitecturecansavetime.Beforestartingyourproject,youmayfigureoutwhatisthegeneralstructureofyoursemanticcheckandcodegenerator.Wehaveblockstoprocessstatementsandexpressionsandothersub-blocksashelpers.Startearlyandkeepgoing.

  • 54

    Jiafei:This ismy first time Ihavebeen inNewYorkandstudied inColumbiaUniversityasavisitingstudent. Frankly speaking, I have gained a lot from this course. First of all, I gained a deepunderstandingtowardshowlanguagesandtheirfeatureswereimplemented.Beforethisclass,Ialways complain about the language I use about why it could not be more convenient forprogrammerstouse,nowIfeelappreciatetothosewhodesignedtheselanguagesandrespecttheselanguagesfromthebottomofmyheart.Besides,thisisalsomyfirsttimeIhavestudiedandusedfunctionalprogramminglanguage,whichoffermeapreciousopportunitytobroadenmyprogrammingthinking.Additionally,thisprojectmademerealizetheimportanceofageneralviewofthewholeproject.IwasanxioustogetdowntocodingassoonasIthoughtIwasabletodosomethingfortheproject,however,afterseveralhoursworkingIjustdeletedallmycodesbecauseIfoundthemuseless.Aftertalkingwithoneofthegroupmember,IrealizedthatIwaslackofageneralviewofthewholeproject,whichresultedinmydifficultyingettingstartindetail.IbelievethegeneralthinkingIlearnedfromthisprojectwillbeofgreatimportancetomyfuturestudy.TherearetwosuggestionIwouldliketooffertofuturegroup.First,makeaplanearlyandgettostartearly.Thisissignificanttonotjustavoidlast-minutecrunchbutcompleteasatisfyingprojectand get the most out of this course. Secondly, teamwork is the next thing I would like toemphasize.Atfirst,wehadgroupmeetingonceaweek,butlaterwefounditwasnotenoughand we had meeting several times a week, and in fact this increased our efficiency a lot.Wheneveryouencounterwithdifficulties,youcouldaskyourgroupmembersforhelp,becausethegroupcanprovideanimportantresourceforthewholeproject,includingaskingquestionsaswellasdecidingonthebestplanforimplementinglanguagefeatures.Zihan:ThemostimportantthingIlearnedfromthisprojectishowtouseGithubtoworktogether.I'veneverdonesuchalargeprojectlikeLIVAonGithub.IthinkGitbubisreallyaclearandefficienttoolforteamcoding.In addition, having a consistent coding style andnaming convention is really important for aprojectteam.Blockcommentsabovefunctiondefinitionsarecritical.Wearsunscreen.Variableandfunctionnamesshouldtellthereaderwhatitisusedfor.Ocamlisalsoaninterestingprogramminglanguageforme.Functionalprogrammingisimpressive.Yanan:

    1. Itisalwaysbettertostarttheprojectasearlyasyoucan.Timeiseverytightforsummersessionandonesmallissuecouldcostyouawholedaytofigureout.Itisvery

  • 55

    importanttosetupasuitableprojectplanandthedeadlineforeachmilestone.Followupthetimelinestrictlyanddon’tdelaythesubtaskimplementation.

    2. Spendenoughtimeindesigningasuitablearchitectureatearlystages.Thiscouldsavealotoftimetoavoidmodifyingthearchitecturefornewfeaturesaddedin.

    3. Itisagoodwaytodividethetotalprojectintosubtasksandassignthesubtaskstothegroupmembers.Butmakesuretomakeactivecommunicationwithothergroupmembersandhaveeachmembersomefamiliaritytoeachpart,makingiteasiertomakechangesiteratively.

    4. GitHubisagoodsoftwaredevelopmenttoolanditcouldimprovetheefficiencyifwelearnhowtobetteruseit.However,therecouldalsobeabigwasteoftimeifwehaveawrongoperationsuchaspushingbeforecommitorforgettingaboutpushing.WehavemetsomeproblemswithpushingnewstufftoGitHubremotely.Someupdatesaremissingandwewerenotsurewhathappenedforthisproblem.

    5. Avoidwastetimeondoingtheduplicatedwork!Discusswiththegroupmembersandknoweachother’sprogressonthesametask.

    6. Trustourgroupmemberssincerelybutalsokeepalertoneverypossibleproblemduringtheprojectdevelopmentprocess.

    7. IwillnotchoosetocompileourlanguagetoLLVMIRsincethereissofewreferenceonteachinghowtouseOCamltowriteaLLVMIRcodegenerator.Ittookusalotoftimetosearchforthegoodandusefulreferencesforthisproject.

    Kate:Mymost important lesson this term is tomeetgood teammates, for thiswas the firstgroupprojectIparticipatedinotherthanlabgroups.Tohavegoodteammates,itiscrucialtobethegood teammateyourself, anddespitemydifficult situation,my teammatesacceptedmeandhelpedmeoutgreatly.

    Chapter 8 Appendix scanner.mll{ openParser letdepth=ref0

  • 56

    letunescapes= Scanf.sscanf("\""^s^"\"")"%S%!"(funx->x)}letwhitespace=['''\t''\r''\n']letascii=([''-'!''#'-'['']'-'~'])letalpha=['a'-'z''A'-'Z']letdigit=['0'-'9']letid=alpha(alpha|digit|'_')*letint=digit+letfloat=(digit+)'.'(digit+)letchar='''(ascii)'''letescape='\\'['\\'''''"''n''r''t']letescape_char='''(escape)'''letstring='"'((ascii|escape)*ass)'"'ruletoken=parse whitespace{tokenlexbuf}|"/*"{incrdepth;commentlexbuf}(*separator*)|'('{LPAREN}|')'{RPAREN}|'{'{LBRACE}|'}'{RBRACE}|';'{SEMI}|','{COMMA}|'.'{DOT}(*Operators*)|'+'{PLUS}|'-'{MINUS}|'*'{TIMES}|'/'{DIVIDE}|'%'{MODULO}|'='{ASSIGN}|"=="{EQ}|"!="{NEQ}|'

  • 57

    |">="{GEQ}|"&"{AND}|"|"{OR}|"!"{NOT}|'['{LBRACKET}|']'{RBRACKET}(*BranchControl*)|"if"{IF}|"else"{ELSE}|"for"{FOR}|"while"{WHILE}|"return"{RETURN}(*DataTypes*)|"int"{INT}|"float"{FLOAT}|"boolean"{BOOLEAN}|"char"{CHAR}|"void"{VOID}|"null"{NULL}|"true"{TRUE}|"false"{FALSE}(*Classes*)|"class"{CLASS}|"constructor"{CONSTRUCTOR}|"extends"{EXTENDS}|"this"{THIS}|"new" {NEW}|intaslxm{INT_LITERAL(int_of_stringlxm)}|floataslxm{FLOAT_LITERAL(float_of_stringlxm)}|charaslxm{CHAR_LITERAL(String.getlxm1)}|escape_charaslxm{CHAR_LITERAL(String.get(unescapelxm)1)}|string {STRING_LITERAL(unescapes)}|idaslxm{ID(lxm)}|eof{EOF}|_asillegal{raise(Failure("illegalcharacter"^Char.escapedillegal))}andcomment=parse "*/" {decrdepth;if!depth>0thencommentlexbufelsetokenlexbuf}

  • 58

    |"/*" {incrdepth;commentlexbuf}|_{commentlexbuf}ast.mltypeop=Add|Sub|Mult|Div|Equal|Neq|Less|Leq|Greater|Geq|And|Not|Or|Modtypeprimitive=Int_t|Float_t|Void_t|Bool_t|Char_t|String_t|Objecttypeofstring|ConstructorType|Null_ttypedatatype=Arraytypeofprimitive*int|Datatypeofprimitive|Anytypeextends=NoParent|Parentofstringtypefname=Constructor|FNameofstringtypeformal=Formalofdatatype*string|Manyofdatatypetypeexpr= Int_Litofint | Boolean_Litofbool | Float_Litoffloat | String_Litofstring | Char_Litofchar | This(*needtobeimplemented*) | Idofstring | Binopofexpr*op*expr | Assignofexpr*expr | Noexpr | ArrayCreateofdatatype*exprlist | ArrayAccessofexpr*exprlist | ObjAccessofexpr*expr | Callofstring*exprlist |ObjectCreateofstring*exprlist | Unopofop*expr | Nulltypestmt= Blockofstmtlist | Exprofexpr | Returnofexpr | Ifofexpr*stmt*stmt | Forofexpr*expr*expr*stmt | Whileofexpr*stmt

  • 59

    |Localofdatatype*string*exprtypefield=Fieldofdatatype*stringtypefunc_decl={ fname:fname; returnType:datatype; formals:formallist; body:stmtlist; overrides:bool; rootcname:stringoption; }typecbody={ fields:fieldlist; constructors:func_decllist; methods:func_decllist;}typeclass_decl={ cname:string; extends:extends; cbody:cbody;}typeprogram=Programofclass_decllist(*getfunctionname,tellconstructorfromordinaryfunctions*)letstring_of_fname=function Constructor->"constructor" | FName(s) ->sletstring_of_primitive=function(*primitivetype*) Int_t ->"int" | Float_t ->"float" | Void_t ->"void" | Bool_t ->"bool" | Char_t ->"char" | Objecttype(s) ->"class"^""^s | ConstructorType ->"constructor" | Null_t ->"null" |String_t->"String"

  • 60

    letstring_of_object=function Datatype(Objecttype(s)) ->s | _->""letrecprint_brackets=function 1->"[]" | a->"[]"^print_brackets(a-1)letstring_of_expre="remaintobecompleted"letstring_of_datatype=function(*datatype*) Arraytype(p,i)->(string_of_primitivep)^(print_bracketsi) | Datatype(p) ->(string_of_primitivep) | Any ->"Any" letstring_of_op=function(*operator*) Add ->"+" | Sub ->"-" | Mult ->"*" | Div ->"/" | Equal ->"==" | Neq ->"!=" | Less ->"" | Geq ->">=" | And ->"and" | Not ->"not" | Or ->"or" | Mod ->"%"letstring_of_booleanb=matchbwith true->"true" |false->"false"

  • 61

    parser.mly%{openAst%}%tokenCLASSEXTENDSCONSTRUCTORDOTTHIS%tokenINTFLOATBOOLEANCHARVOIDNULLTRUEFALSE%tokenSEMILPARENRPARENLBRACERBRACELBRACKETRBRACKETCOMMA%tokenANDNOTORPLUSMINUSTIMESDIVIDEASSIGNMODULO%tokenEQNEQLTLEQGTGEQ%tokenRETURNIFELSEFORWHILENEW%tokenINT_LITERAL%tokenFLOAT_LITERAL%tokenSTRING_LITERAL%tokenID%tokenCHAR_LITERAL%tokenEOF%nonassocNOELSE%nonassocELSE%rightASSIGN%leftANDOR%leftEQNEQ%leftLTGTLEQGEQ%leftPLUSMINUS%leftTIMESDIVIDEMODULO%rightNOT%rightRBRACKET%leftLBRACKET%rightDOT%startprogram%typeprogram%%program: cdeclsEOF{Program($1)}/******************CLASSES

  • 62

    ******************/cdecls:cdecl_list{List.rev$1}cdecl_list:cdecl{[$1]}|cdecl_listcdecl{$2::$1}cdecl: CLASSIDLBRACEcbodyRBRACE{{ cname=$2; extends=NoParent; cbody=$4 }} | CLASSIDEXTENDSIDLBRACEcbodyRBRACE{{ cname=$2; extends=Parent($4); cbody=$6 }}cbody: /*nothing*/{{ fields=[]; constructors=[]; methods=[]; }} | cbodyfield{{ fields=$2::$1.fields; constructors=$1.constructors; methods=$1.methods; }} | cbodyconstructor{{ fields=$1.fields; constructors=$2::$1.constructors; methods=$1.methods; }} | cbodyfdecl{{ fields=$1.fields; constructors=$1.constructors; methods=$2::$1.methods; }}

  • 63

    /******************CONSTRUCTORS******************/constructor: CONSTRUCTORLPARENformals_optRPARENLBRACEstmt_listRBRACE{ { fname=Constructor; returnType=Datatype(ConstructorType); formals=$3; body=List.rev$6; overrides=false;rootcname=None; } }/******************FIELDS******************//*publicUserObjname;*/field: datatypeIDSEMI{Field($1,$2)}/******************METHODS******************/fname: ID{$1}fdecl: datatypefnameLPARENformals_optRPARENLBRACEstmt_listRBRACE { { fname=FName($2); returnType=$1;

  • 64

    formals=$4; body=List.rev$7; overrides=false;rootcname=None; } }/******************FORMALS/PARAMETERS&VARIABLES&ACTUALS******************/formals_opt: /*nothing*/{[]} | formal_list{List.rev$1}formal_list: formal{[$1]} | formal_listCOMMAformal{$3::$1}formal: datatypeID{Formal($1,$2)}actuals_opt: /*nothing*/{[]} | actuals_list{List.rev$1}actuals_list: expr{[$1]} | actuals_listCOMMAexpr{$3::$1}/*************** DATATYPES***************/primitive: INT {Int_t} | FLOAT {Float_t} | CHAR {Char_t} | BOOLEAN {Bool_t} | VOID {Void_t}name:

  • 65

    CLASSID{Objecttype($2)}type_tag: primitive{$1} | name {$1}array_type: type_tagLBRACKETbracketsRBRACKET{Arraytype($1,$3)}datatype: type_tag{Datatype($1)} | array_type{$1}brackets: /*nothing*/ {1} | bracketsRBRACKETLBRACKET{$1+1}/******************EXPRESSIONS******************/stmt_list: /*nothing*/{[]} |stmt_liststmt{$2::$1}stmt: exprSEMI{Expr($1)} | RETURNexprSEMI{Return($2)} | RETURNSEMI {Return(Noexpr)} | LBRACEstmt_listRBRACE{Block(List.rev$2)} | IFLPARENexprRPARENstmt%precNOELSE{If($3,$5,Block([Expr(Noexpr)]))} | IFLPARENexprRPARENstmtELSEstmt{If($3,$5,$7)} | FORLPARENexpr_optSEMIexpr_optSEMIexpr_optRPARENstmt {For($3,$5,$7,$9)} | WHILELPARENexprRPARENstmt {While($3,$5)} |datatypeIDSEMI {Local($1,$2,Noexpr)} | datatypeIDASSIGNexprSEMI {Local($1,$2,$4)}expr_opt: /*nothing*/{Noexpr} | expr{$1}expr:

  • 66

    literals {$1} | exprPLUSexpr {Binop($1,Add,$3)} | exprMINUSexpr {Binop($1,Sub,$3)} | exprTIMESexpr {Binop($1,Mult,$3)} | exprDIVIDEexpr {Binop($1,Div,$3)} | exprEQexpr {Binop($1,Equal,$3)} | exprNEQexpr {Binop($1,Neq,$3)} | exprLTexpr {Binop($1,Less,$3)} | exprLEQexpr {Binop($1,Leq,$3)} | exprGTexpr {Binop($1,Greater,$3)} | exprGEQexpr {Binop($1,Geq,$3)} | exprANDexpr {Binop($1,And,$3)} | exprMODULOexpr {Binop($1,Mod,$3)} | NOTexpr {Unop(Not,$2)} | exprORexpr {Binop($1,Or,$3)} | exprDOTexpr {ObjAccess($1,$3)} | exprASSIGNexpr {Assign($1,$3)} |MINUSexpr {Unop(Sub,$2)} | IDLPARENactuals_optRPAREN {Call($1,$3)} | NEWIDLPARENactuals_optRPAREN {ObjectCreate($2,$4)} | NEWtype_tagbracket_argsRBRACKET {ArrayCreate(Datatype($2),List.rev$3)} | exprbracket_argsRBRACKET {ArrayAccess($1,List.rev$2)} | LPARENexprRPAREN {$2}bracket_args: LBRACKETexpr {[$2]} | bracket_argsRBRACKETLBRACKETexpr{$4::$1}literals: INT_LITERAL {Int_Lit($1)} |FLOAT_LITERAL {Float_Lit($1)} |TRUE {Boolean_Lit(true)} |FALSE {Boolean_Lit(false)} |STRING_LITERAL {String_Lit($1)} |CHAR_LITERAL {Char_Lit($1)} |THIS {This} |ID {Id($1)} |NULL {Null}sast.ml

  • 67

    openAsttypesexpr= SInt_Litofint | SBoolean_Litofbool | SFloat_Litoffloat | SString_Litofstring | SChar_Litofchar | SIdofstring*datatype | SBinopofsexpr*op*sexpr*datatype | SAssignofsexpr*sexpr*datatype | SNoexpr | SArrayCreateofdatatype*sexprlist*datatype | SArrayAccessofsexpr*sexprlist*datatype | SObjAccessofsexpr*sexpr*datatype | SCallofstring*sexprlist*datatype*int |SObjectCreateofstring*sexprlist*datatype | SArrayElementsofsexprlist*datatype | SUnopofop*sexpr*datatype | SNulltypesstmt= SBlockofsstmtlist | SExprofsexpr*datatype | SReturnofsexpr*datatype | SIfofsexpr*sstmt*sstmt | SForofsexpr*sexpr*sexpr*sstmt | SWhileofsexpr*sstmt |SLocalofdatatype*string*sexprtypefunc_type=User|Reservedtypesfunc_decl={ sfname:fname; sreturnType:datatype; sformals:formallist; sbody:sstmtlist; functype:func_type; source:string; overrides:bool;}

  • 68

    typesclass_decl={ scname:string; sfields:fieldlist; sfuncs:sfunc_decllist;}(*ClassDeclarations|Allmethoddeclarations|Mainentrymethod*)typesprogram={ classes:sclass_decllist; functions:sfunc_decllist; main:sfunc_decl; reserved:sfunc_decllist;}semant.ml(*SemanticcheckingfortheLivacompiler*)openAstopenSast(*Semanticcheckingofaprogram.ReturnsSastifsuccessful,throwsanexceptionifsomethingiswrong.*)(*globalvariablesandhelpferfunctions*)moduleStringMap=Map.Make(String)moduleStringSet=Set.Make(String)moduleSS=Set.Make( struct letcompare=Pervasives.compare typet=datatype end)typeclassMap={ fieldMap:Ast.fieldStringMap.t; functionMap:Ast.func_declStringMap.t; constructorMap:Ast.func_declStringMap.t; builtFuncMap:sfunc_declStringMap.t; cdecl :Ast.class_decl;}

  • 69

    typeenv={ envClassMaps:classMapStringMap.t; envName:string; envClassMap:classMap; envLocals:datatypeStringMap.t; envParams:Ast.formalStringMap.t; envReturnType:datatype; envInFor:bool; envInWhile:bool; envBuiltIn:sfunc_decllist;}letupdateEnvenvenvName={ envClassMaps=env.envClassMaps; envName=envName; envClassMap =env.envClassMap; envLocals=env.envLocals; envParams=env.envParams; envReturnType=env.envReturnType; envInFor=env.envInFor; envInWhile=env.envInWhile; envBuiltIn=env.envBuiltIn;}letstrucIndexes:(string,int)Hashtbl.t=Hashtbl.create10letinheritanceRelation:(string,stringlist)Hashtbl.t=Hashtbl.create10letcreateStructIndexescdecls= letclassHandlerindexcdecl= Hashtbl.addstrucIndexescdecl.cnameindexin List.itericlassHandlercdeclsletdefaultC={ fname=Ast.Constructor; returnType=Datatype(ConstructorType); formals=[]; body=[]; overrides =false;

  • 70

    rootcname =None;}letgetNamecnamefdecl=(*getthenameoffunction,cname.constructor->constructor/cname.xxx->normal_function/main*) letname=string_of_fnamefdecl.fname(*tellconstructorfromnormalfunction*) in matchnamewith "main"->"main" |_ ->cname^"."^name lettypOFSexpr=function(*getthetypeofsexpression*) SInt_Lit(_) ->Datatype(Int_t) | SBoolean_Lit(_) ->Datatype(Bool_t) | SFloat_Lit(_) ->Datatype(Float_t) | SString_Lit(_) ->Arraytype(Char_t,1) | SChar_Lit(_) ->Datatype(Char_t) | SId(_,d) ->d | SBinop(_,_,_,d) ->d | SAssign(_,_,d) ->d | SNoexpr ->Datatype(Void_t) | SArrayCreate(_,_,d) ->d | SArrayAccess(_,_,d) ->d | SObjAccess(_,_,d) ->d | SCall(_,_,d,_) ->d |SObjectCreate(_,_,d) ->d | SArrayElements(_,d) ->d | SUnop(_,_,d) ->d | SNull ->Datatype(Null_t) (****EntrypointfortranslatingAsttoSast*****)letcheckprogram= (*addreservedbuilt-infunctions*) letstoreBuiltinFunctions= leti32_t=Datatype(Int_t)and void_t=Datatype(Void_t)and str_t=Arraytype(Char_t,1) in letmfts=Formal(t,s)

  • 71

    in letbuiltinStubfnamereturnTypeformals= { sfname=FName(fname); sreturnType=returnType; sformals=formals; functype=Sast.Reserved; sbody=[]; overrides =false; source="NA" } in letbuiltinFunctions=[ builtinStub"print" (void_t) ([Many(Any)]); builtinStub"malloc" (str_t)([mfi32_t"size"]); builtinStub"cast" (Any) ([mfAny"in"]); ] inbuiltinFunctions in letbuiltinFunctions=storeBuiltinFunctions in (*createclassmaps*) letgetConstructorNamecnamefdecl= letparams=List.fold_left (funsf->matchfwith Formal(t,_)->s^"."^string_of_datatypet |_->"")""fdecl.formals in letname=string_of_fnamefdecl.fname incname^"."^name^params in letmappingClassbuiltinFunctionscdecls= letbuiltFuncMap= List.fold_left(funmpsfunc->StringMap.add(string_of_fnamesfunc.sfname)sfuncmp)StringMap.emptybuiltinFunctions in

  • 72

    letassistantmpcdecl= letfieldpartmp=functionField(d,n)-> if(StringMap.memnmp) thenraise(Failure("DuplicatedField:"^n)) else(StringMap.addn(Field(d,n))mp) in letconstructorpartcondecl= ifList.lengthcondecl>1 thenraise(Failure("DuplicatedConstructor")) elseifList.lengthcondecl=0(*defaultconstructor*) thenStringMap.add(getConstructorNamecdecl.cnamedefaultC)defaultCStringMap.empty else StringMap.add(getConstructorNamecdecl.cname(List.hdcondecl))(List.hdcondecl)StringMap.empty in letfuncpartmfdecl= letfunname=getNamecdecl.cnamefdecl in if(StringMap.memfunnamemp) thenraise(Failure("DuplicatedFunction:"^funname)) else letstrfunname=string_of_fnamefdecl.fname in if(StringMap.memstrfunnamebuiltFuncMap) thenraise(Failure("Cannotusethereservedbuit-infunctionname:"^strfunname)) else(StringMap.add(getNamecdecl.cnamefdecl)fdeclm) in (if(StringMap.memcdecl.cnamemp) thenraise(Failure("Duplicatedclassname:"^cdecl.cname)) else StringMap.addcdecl.cname { fieldMap=List.fold_leftfieldpartStringMap.emptycdecl.cbody.fields;

  • 73

    constructorMap=constructorpartcdecl.cbody.constructors; functionMap=List.fold_leftfuncpartStringMap.emptycdecl.cbody.methods; builtFuncMap=builtFuncMap; cdecl=cdecl }mp) inList.fold_leftassistantStringMap.emptycdecls in matchprogramwith Program(classes)->ignore(createStructIndexesclasses); letclassMaps=mappingClassbuiltinFunctionsclasses in (*convertstatementinAsttostatementinSast*) letrecexprToSexprenv=function Int_Liti->SInt_Lit(i),env |Boolean_Litb->SBoolean_Lit(b),env |Float_Litf->SFloat_Lit(f),env |String_Lits->SString_Lit(s),env |Char_Litc->SChar_Lit(c),env |This->SId("this",Datatype(Objecttype(env.envName))),env |Ids->SId(s,getIDTypeenvs),env |Null->SNull,env |Noexpr->SNoexpr,env |ObjAccess(e1,e2)->checkObjAccessenve1e2,env |ObjectCreate(s,el)->checkConstructorenvsel,env |Call(s,el)->checkCallTypeenvsel,env |ArrayCreate(d,el)->checkArrayInitializeenvdel,env |ArrayAccess(e,el)->checkArrayAccessenveel,env |Assign(e1,e2)->checkAssignenve1e2,env |Unop(op,e)->checkUnopenvope,env |Binop(e1,op,e2)->checkBinopenve1ope2,env andexprsToSexprsenvel=(*convertexpressionlisttosexpressionlist*) letenvref=refenv in letrecassistant=function h::t->letnewh,env=exprToSexpr!envrefh

  • 74

    in( envref:=env; newh::(assistantt)) |[]->[] in (assistantel),!envref andgetIDTypeenvs= try StringMap.findsenv.envLocals with |Not_found->tryletformal=StringMap.findsenv.envParams in(functionFormal(t,_)->t |Manyt->t)formal with|Not_found->raise(Failure("IDisundefined:"^s)) andcheckArrayInitializeenvdel= letarraySize=List.lengthel(*getthedimentionofarray*) in letcheckIndexTypee=(*checkwhetherthetypeofindexisint*) letsexpr,_=exprToSexprenve(*convertexpressiontosexpression*) in lettyp=typOFSexprsexpr(*getthetypeofsexpression*) in iftyp=Datatype(Int_t) thensexpr elseraise(Failure("Invalidindextypeforarrayinitialization:"^string_of_datatypetyp)) in letcheckTyp=function(*checkwhetherthetypecanbearraytype*) Datatype(x)->Arraytype(x,arraySize) |_ast->raise(Failure("Invalidarraytype:"^(string_of_datatypet))) in lettyp=checkTypd in letsel=List.mapcheckIndexTypeel in SArrayCreate(d,sel,typ) andcheckArrayAccessenveel=

  • 75

    letarraySize=List.lengthel(*getthesizeofarray*) in letcheckIndexTypearg=(*checkwhetherthetypeofindexisint*) letsexpr,_=exprToSexprenvarg(*convertexpressiontosexpression*) in lettyp=typOFSexprsexpr(*getthetypeofsexpression*) in iftyp=Datatype(Int_t) thensexpr elseraise(Failure("Invalidindextypeforarrayaccess:"^string_of_datatypetyp)) in letse,_=exprToSexprenve(*convertexpressiontosexpression*) in lettyp=typOFSexprse(*getthetypeofsexpression*) in letcheckArraySizenum=function Arraytype(t,n)->ifnum=n thenDatatype(t) elseraise(Failure("Invaliddementionforarrayaccess:"^(string_of_intnum)^">"^(string_of_intn))) |_ast->raise(Failure("Invalidtypeforarrayaccess:"^(string_of_datatypet))) in lettyp=checkArraySizearraySizetyp in letsel=List.mapcheckIndexTypeel inSArrayAccess(se,sel,typ) andcheckObjAccessenvlhsrhs= letcheckLHS=function(*checktheexpressionbefore‘.’andgetsexpression*) This ->SId("this",Datatype(Objecttype(env.envName))) |Ids ->SId(s,getIDTypeenvs) |ArrayAccess(e,el) ->checkArrayAccessenveel |_ ->raise(Failure("LHSofobjectaccessmustbeaninstanceofcertainclass")) in

  • 76

    letgetCnamelhsTyp=matchlhsTypwith(*getthetypeoftheexpressionbefore‘.’,i.e.classname*) Datatype(Objecttype(name))->name | _asd ->raise(Failure("Objectaccessmustha