Advertisement
Guest User

Untitled

a guest
May 25th, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 23.77 KB | None | 0 0
  1. package ba140645d.mjcompiler;
  2.  
  3.  
  4. import ba140645d.mjcompiler.ast.*;
  5. import rs.etf.pp1.mj.runtime.Code;
  6. import rs.etf.pp1.symboltable.Tab;
  7. import rs.etf.pp1.symboltable.concepts.Obj;
  8. import rs.etf.pp1.symboltable.concepts.Struct;
  9.  
  10. import java.util.*;
  11.  
  12. public class CodeGenerator extends VisitorAdaptor {
  13.  
  14.  
  15.     private static final String ORD_METH_NAME = "ord";
  16.  
  17.     private static final String CHR_METH_NAME = "chr";
  18.  
  19.     private static final String LEN_METH_NAME = "len";
  20.  
  21.     private static final String MAIN_METH_NAME = "main";
  22.  
  23.     private static final int ALLOC_BYTES = 0;
  24.  
  25.     private static final int ALLOC_WORDS = 1;
  26.  
  27.     private Obj designatorObj = Tab.noObj;
  28.  
  29.     private static final Obj minus1constObj = new Obj(Obj.Con, "", Tab.intType, -1, 0);
  30.  
  31.     private static final Obj num1constObj = new Obj(Obj.Con, "", Tab.intType, 1, 0);
  32.  
  33.     private static final Obj num0constObj = new Obj(Obj.Con, "", Tab.intType, 0, 0);
  34.  
  35.  
  36.     // stek koji pamti mesta za prepravljanje adresa skokova
  37.     // gde treba da skocimo ako je uslov true
  38.     private Stack<List<Integer>> truePatchStack = new Stack<>();
  39.  
  40.     // stek koji pamti mesta za prepravljanje adresa skokova
  41.     // gde treba da skocimo ako je uslov false
  42.     private Stack<List<Integer>> falsePatchStack = new Stack<>();
  43.  
  44.     // pamti se adresa za prepravljanje, gde se nakon zavrsetka then grane
  45.     // skace na kraj if/else
  46.     private Stack<Integer> thenJumpPatchStack = new Stack<>();
  47.  
  48.  
  49.     // pamcenje adrese pocetka naredbi  do-while petlje
  50.     private Stack<Integer> whileBeginStack = new Stack<>();
  51.  
  52.     // pamcenje adrese kraja naredbi do-while petlje
  53.     private Stack<Integer> whileEndStack = new Stack<>();
  54.  
  55.     // stek na kome cemo pamtiti adrese gde se javlja naredba break
  56.     private Stack<List<Integer>> breakStatementAdrStack = new Stack<>();
  57.  
  58.     // stek na kome cemo pamtiti adrese na kojima se javlja naredba continue;
  59.     private Stack<List<Integer>> continueStatementAdrStack = new Stack<>();
  60.  
  61.     // svi simboli programa
  62.     private HashMap<String, Obj> programSymbols = new HashMap<>();
  63.  
  64.  
  65.  
  66.     /**
  67.      * Generise kod za predefinisane metode
  68.      * Predefinisane metode su : ord, chr, len
  69.      */
  70.     private void generateCodeForPredefinedMethods(){
  71.         // simboli iz scope-a univerzuma
  72.         Collection<Obj> universeSymbols = Tab.currentScope.getLocals().symbols();
  73.  
  74.         // kod universe scope-a postoje predefinisani tipovi podataka, metode
  75.         // i naziv programa, od interesa su nam samo predefinisane metode
  76.         // i za njih zelimo da generisemo kod
  77.         universeSymbols.forEach((universeSymbol)->{
  78.             // ako nije metoda, ne obradjujemo
  79.             if (universeSymbol.getKind() != Obj.Meth)
  80.                 return;
  81.  
  82.             // postavljamo adresu funkcije na trenutni pokazivac PC-a
  83.             universeSymbol.setAdr(Code.pc);
  84.  
  85.             // instrukcija koja frsi pamcenje stack pointera, function pointera i
  86.             // inicijalizuje prostor za parametre i lokalne promenljive
  87.             Code.put(Code.enter);
  88.  
  89.             // format enter instrukcije je enter paramSize, Lsize gde je Lsize ukupan prostor
  90.             // koji zauzimaju
  91.  
  92.             // prvo ide broj parametara
  93.             Code.put(universeSymbol.getLevel());
  94.  
  95.             // pa ukupan broj lokalnih simbola(parametri + lokalne promenljive)
  96.             Code.put(universeSymbol.getLocalSymbols().size());
  97.  
  98.             // ucitamo vrednost parametra u expr stek
  99.             Code.put(Code.load_n);
  100.  
  101.             // ukoliko je metoda len u pitanju, onda treba pored gore navedenih akcija
  102.             // takodje i dodati instrukciju arraylength, koja ce nam dati duzinu samog niza
  103.             if (universeSymbol.getName().equals("len"))
  104.                 Code.put(Code.arraylength);
  105.  
  106.             // kao i kod x86 jednostavno uklonimo sve lokalne promenljive sa steka
  107.             // i bp(ovde je to fp) vratimo na prethodnu vrednost
  108.             Code.put(Code.exit);
  109.  
  110.             // narebom return napustamo funkciju  pc = pop();
  111.             Code.put(Code.return_);
  112.         });
  113.     }
  114.  
  115.  
  116.     private void storeDesignator(Obj designatorObj){
  117.         if (designatorObj.getKind() != Obj.Elem)
  118.             Code.store(designatorObj);
  119.         else if (designatorObj.getType() == Tab.intType)
  120.             Code.put(Code.astore);
  121.         else
  122.             Code.put(Code.bastore);
  123.     }
  124.  
  125.     private void loadDesignator(Obj designatorObj){
  126.         if (designatorObj.getKind() != Obj.Elem)
  127.             Code.load(designatorObj);
  128.         else if (designatorObj.getType() == Tab.intType)
  129.             Code.put(Code.aload);
  130.         else
  131.             Code.put(Code.baload);
  132.     }
  133.  
  134.  
  135.     private int getRelopCode(Relop  relop){
  136.         if (relop instanceof  RelopEquals)
  137.             return Code.eq;
  138.         else if (relop instanceof  RelopNotEquals)
  139.             return Code.ne;
  140.         else if (relop instanceof  RelopGreater)
  141.             return Code.gt;
  142.         else if (relop instanceof RelopGreaterEqual)
  143.             return Code.ge;
  144.         else if (relop instanceof  RelopLesser)
  145.             return Code.lt;
  146.         else if (relop instanceof RelopLesserEqual)
  147.             return Code.le;
  148.  
  149.  
  150.         // nikad nece doci do ovoga
  151.         return Code.eq;
  152.     }
  153.  
  154.     /**
  155.      * Prepravlja relativni skok na adresama datim u listi
  156.      * @param adrsToFixupList lista adresa gde treba prepravljati
  157.      */
  158.     private void fixupAddresses(List<Integer> adrsToFixupList){
  159.         for(Integer adrToFixup : adrsToFixupList)
  160.             Code.fixup(adrToFixup);
  161.     }
  162.  
  163.  
  164.     /**
  165.      * Metoda koja prepravlja adrese koje treba da skoce na pocetak do/while petlje
  166.      * @param adrsToPatchList lista adresa za prepravljanje
  167.      */
  168.     private void doWhileFixup(List<Integer> adrsToPatchList, int doWhileStartAdr){
  169.  
  170.         for(int adrToPatch : adrsToPatchList)
  171.             Code.put2(adrToPatch, doWhileStartAdr - Code.pc + 1);
  172.  
  173.     }
  174.  
  175.     /**
  176.      * Metoda koja prepravlja adresu koja treba da skoci na pocetak do/while petlje
  177.      * @param adrToPatch adresa koja se prepravlja
  178.      */
  179.     private void doWhileFixup(int adrToPatch){
  180.         Code.put2(adrToPatch, adrToPatch - Code.pc + 1);
  181.     }
  182.  
  183.     @Override
  184.     public void visit(Program program){
  185.         Tab.closeScope();
  186.     }
  187.  
  188.     @Override
  189.     public void visit(ProgramName programName){
  190.  
  191.         // generisanje koda za predefinisane metode
  192.         generateCodeForPredefinedMethods();
  193.  
  194.         Obj programObj = Tab.find(programName.getProgramName());
  195.  
  196.         // simboli iz scope-a programa
  197.         Collection<Obj> programSymbols = programObj.getLocalSymbols();
  198.  
  199.         // otvaranje opsega zarad lakseg nalazenja simbola
  200.         Tab.openScope();
  201.  
  202.         // dodavanje simbola programa u trenutni opseg
  203.         // moramo da navedemo koliko prostora treba da zauzimaju globalne promenljive, velicina
  204.         // se izrazava u recima(jedna rec je 4 bajta)
  205.         programSymbols.forEach((symbol)->{
  206.             Tab.currentScope().addToLocals(symbol);
  207.             if (symbol.getKind() == Obj.Var)
  208.                 Code.dataSize++;
  209.         });
  210.     }
  211.  
  212.  
  213.     @Override
  214.     public void visit(MethodName method){
  215.         String methodName = method.getMethodName();
  216.  
  217.         Obj methodObj = Tab.find(methodName);
  218.  
  219.         // ukoliko je u pitanju main metoda, moramo navesti koja je njena adresa
  220.         if (methodName.equals(MAIN_METH_NAME)){
  221.             Code.mainPc = Code.pc;
  222.         }
  223.  
  224.         // namestamo adresu metode na trenutnu vrednost pc
  225.         methodObj.setAdr(Code.pc);
  226.  
  227.         // broj formalnih parametara
  228.         int paramNum = methodObj.getLevel();
  229.  
  230.         // ukupan broj lokalnih simbola u metodi( parametri + promenljive)
  231.         int localSymbolNum = methodObj.getLocalSymbols().size();
  232.  
  233.         // kod za inicijalizaciju metode pri ulasku, instrukcija ima 2 parametra
  234.         // broj parametara i ukupan broj lokalnih simbola
  235.         Code.put(Code.enter);
  236.  
  237.         // prvo ide broj parametara
  238.         Code.put(paramNum);
  239.  
  240.         // pa zatim i ukupan broj simbola
  241.         Code.put(localSymbolNum);
  242.  
  243.  
  244.         //  otvorimo scope zarad lakse pretrage simbola
  245.         Tab.openScope();
  246.  
  247.         // dohvatimo sve simbole metode
  248.         Collection<Obj> methodSymbols = methodObj.getLocalSymbols();
  249.  
  250.         // dodamo ih u scope
  251.         for (Obj methodSymbol : methodSymbols) {
  252.             Tab.currentScope.addToLocals(methodSymbol);
  253.         }
  254.  
  255.     }
  256.  
  257.     @Override
  258.     public void visit(MethodDecl methodDecl){
  259.         // dohvatimo ime metode
  260.         String methodName = methodDecl.getMethodName().getMethodName();
  261.  
  262.         // dohvatimo objekat(simbol) metode
  263.         Obj methodObj = Tab.find(methodName);
  264.  
  265.         // ciscenje steka od lokalnih simbola
  266.         Code.put(Code.exit);
  267.  
  268.         // vracanje nazad
  269.         Code.put(Code.return_);
  270.     }
  271.  
  272.     @Override
  273.     public void visit(Expr expr){
  274.         expr.struct = expr.getTerm().struct;
  275.     }
  276.  
  277.     @Override
  278.     public void visit(OptMinusDeclared minusOp){
  279.         //Code.load(minus1constObj);
  280.     }
  281.  
  282.  
  283.     @Override
  284.     public void visit(Term term){
  285.         if (term.getParent() instanceof Expr && ((Expr)term.getParent()).getOptMinus() instanceof OptMinusDeclared)
  286.             Code.put(Code.neg);
  287.  
  288.         term.struct = term.getFactor().struct;
  289.     }
  290.  
  291.     @Override
  292.     public void visit(AddopTermListDeclared addopTermList){
  293.         Addop addOp = addopTermList.getAddopTerm().getAddop();
  294.  
  295.         if (addOp instanceof AddopAddition)
  296.                 Code.put(Code.add);
  297.         else if (addOp instanceof  AddopSubtraction)
  298.             Code.put(Code.sub);
  299.  
  300.         addopTermList.struct = addopTermList.getAddopTerm().struct;
  301.     }
  302.  
  303.     @Override
  304.     public void visit(AddopTerm addopTerm){
  305.         addopTerm.struct = addopTerm.getTerm().struct;
  306.     }
  307.  
  308.  
  309.     @Override
  310.     public void visit(MulopFactorListDeclared mulopFactorList){
  311.         Mulop mulop = mulopFactorList.getMulopFactor().getMulop();
  312.  
  313.         if (mulop instanceof  MulopMultiplication)
  314.             Code.put(Code.mul);
  315.         else if (mulop instanceof  MulopDivision)
  316.             Code.put(Code.div);
  317.         else if (mulop instanceof  MulopModuo)
  318.             Code.put(Code.rem);
  319.  
  320.         mulopFactorList.struct = mulopFactorList.getMulopFactor().struct;
  321.     }
  322.  
  323.     @Override
  324.     public void visit(MulopFactor mulopFactor){
  325.         mulopFactor.struct = mulopFactor.getFactor().struct;
  326.     }
  327.  
  328.     @Override
  329.     public void visit(FactorFuncCallOrVar factor){
  330.         Obj designatorObj = factor.getDesignator().obj;
  331.  
  332.  
  333.         if (designatorObj.getKind() == Obj.Meth) {
  334.             Code.put(Code.call);
  335.             // treba nam relativan pomeraj u odnosu na instrukciju call
  336.             Code.put2(designatorObj.getAdr() - Code.pc + 1);
  337.         }else
  338.             loadDesignator(designatorObj);
  339.  
  340.         factor.struct = factor.getDesignator().obj.getType();
  341.     }
  342.  
  343.  
  344.     @Override
  345.     public void visit(FactorConst factorConst){
  346.         ConstValue constValue = factorConst.getConstValue();
  347.  
  348.         // objekat konstante
  349.         Obj constObj = null;
  350.  
  351.         // proverimo kog je tipa konstanta i kreiramo odgovarajuci simbol
  352.         if (constValue instanceof NumConst)
  353.             constObj = new Obj(Obj.Con, "",Tab.intType, ((NumConst) constValue).getNumConst(), 0);
  354.         else if (constValue instanceof  CharConst)
  355.             constObj = new Obj(Obj.Con, "", Tab.charType, ((CharConst) constValue).getCharConst(), 0);
  356.         else if (constValue instanceof  BoolConst)
  357.             constObj = new Obj(Obj.Con, "", SemanticAnalyzer.boolType, ((BoolConst) constValue).getBoolConst() ? 1 : 0, 0 );
  358.  
  359.         Code.load(constObj);
  360.  
  361.         factorConst.struct = constObj.getType();
  362.     }
  363.  
  364.  
  365.     @Override
  366.     public void visit(FactorNew factorNew){
  367.         // ispitujemo da li je alokacija niza
  368.         boolean isArrayAlloc = factorNew.getOptArrExpr() instanceof  OptArrExprDeclared;
  369.  
  370.         Struct newType = Tab.find(factorNew.getType().getTypeName()).getType();
  371.         // za sad ne podrzavamo dinamicku alokaciju tipova, vec samo nizova, semanticka analiza je proverila
  372.         // vec uslov za to, stoga mi ne moramo
  373.  
  374.         Code.put(Code.newarray);
  375.  
  376.         if (newType == Tab.intType)
  377.             Code.put(ALLOC_WORDS);
  378.         else
  379.             Code.put(ALLOC_BYTES);
  380.  
  381.         factorNew.struct = newType;
  382.     }
  383.  
  384.  
  385.     @Override
  386.     public void visit(FactorExpr factorExpr){
  387.         factorExpr.struct = factorExpr.getExpr().struct;
  388.     }
  389.  
  390.  
  391.     /****************************************************************************
  392.      ****************************************************************************
  393.      ******************     VISIT METODE ZA LOGICKE IZRAZE    *******************
  394.      ****************************************************************************
  395.      ****************************************************************************/
  396.  
  397.  
  398.     @Override
  399.     public void visit(Condition condition){
  400.  
  401.     }
  402.  
  403.     @Override
  404.     public void visit(ConditionRepeatList conditionRepeatList){
  405.  
  406.     }
  407.  
  408.     @Override
  409.     public void visit(CondTerm condTerm){
  410.  
  411.     }
  412.  
  413.     @Override
  414.     public void visit(CondFactRepeatList condFactRepeatList){
  415.  
  416.     }
  417.  
  418.     @Override
  419.     public void visit(CondFactRepeat condFactRepeat){
  420.  
  421.     }
  422.  
  423.     @Override
  424.     public void visit(CondFact condFact){
  425.  
  426.         // podrazumevano je poredjenje ne, za slucaj kada je promenljiva samo boolean
  427.         int relopCode = Code.ne;
  428.  
  429.         if (condFact.getOptRelopExpr() instanceof  OptRelopExprDeclared)
  430.             relopCode = getRelopCode(((OptRelopExprDeclared) condFact.getOptRelopExpr()).getRelop());
  431.  
  432.  
  433.         Code.putFalseJump(relopCode, 0);
  434.  
  435.         falsePatchStack.peek().add(Code.pc - 2);
  436.     }
  437.  
  438.     @Override
  439.     public void visit(LogicalOr logicalOr){
  440.         // stavljamo instrukciju jump, nakon sto obradimo sve uslove
  441.         // prepravicemo samu adresu na koju skacemo
  442.         Code.putJump(0);
  443.  
  444.         // adresa za prepravljanje je trenutna - 2 ( da se pozicioniramo na mesto gde
  445.         // treba da se ubaci odgovarajuci pomeraj
  446.         truePatchStack.peek().add(Code.pc - 2);
  447.  
  448.         // treba da prepravimo sve false skokove, i da stavimo
  449.         // da skacu na pocetak ispitivanja trenutnog izraza
  450.         for(Integer adrForPatching : falsePatchStack.peek()){
  451.             Code.fixup(adrForPatching);
  452.         }
  453.  
  454.         falsePatchStack.peek().clear();
  455.     }
  456.  
  457.  
  458.     @Override
  459.     public void visit(LogicalAnd logicalAnd){
  460.  
  461.     }
  462.  
  463.  
  464.  
  465.     @Override
  466.     public void visit(OptRelopExprEpsilon exprEpsilon){
  467.         // sa desne strane nema nikakav izraz, stoga levu stranu poredimo sa 0
  468.         loadDesignator(num0constObj);
  469.     }
  470.  
  471.  
  472.     /****************************************************************************
  473.      ****************************************************************************
  474.      *************     VISIT METODE ZA PRISTUP PROMENLJIVAMA     ****************
  475.      *****************************    I FUNKCIJAMA    ***************************
  476.      ****************************************************************************/
  477.  
  478.     @Override
  479.     public void visit(Designator designator){
  480.         // u pitanju je B nivo, tu imamo samo promenljive i nizove
  481.         // nema klasa, stoga ne moramo da imamo neki poseban kod za pristup poljima objekata
  482.         designator.obj = Tab.find(designator.getDesignatorInitialName().getDesignatorName());
  483.  
  484.  
  485.         // ako nije niz vratimo se
  486.         if (designator.obj.getType().getKind() != Struct.Array)
  487.             return;
  488.  
  489.  
  490.         boolean isElemAccess = designator.getDesignatorRepeatList() instanceof  DesignatorRepeatListDeclared;
  491.  
  492.         if (isElemAccess)
  493.             designator.obj = new Obj(Obj.Elem, "", designator.obj.getType().getElemType());
  494.     }
  495.  
  496.     @Override
  497.     public void visit(DesignatorInitialName designatorInitialName){
  498.         String designatorName = designatorInitialName.getDesignatorName();
  499.  
  500.         designatorObj = Tab.find(designatorName);
  501.  
  502.         // fleg koji oznacava da li pristupamo elementu niza
  503.         boolean isElemAccess = ((Designator)designatorInitialName.getParent()).getDesignatorRepeatList() instanceof  DesignatorRepeatListDeclared;
  504.  
  505.  
  506.         // treba da izgenerismo dodatnu instrukciju za ucitavanje adrese niza
  507.         // ukoliko pristupamo elementu niza
  508.         if (isElemAccess)
  509.             loadDesignator(designatorObj);
  510.     }
  511.  
  512.     /****************************************************************************
  513.      ****************************************************************************
  514.      *********************     VISIT METODE ZA NAREDBE     **********************
  515.      ****************************************************************************
  516.      ****************************************************************************/
  517.  
  518.  
  519.     @Override
  520.     public void visit(PrintStatement printStatement){
  521.  
  522.         // ako je izraz charType onda radimo ispis karaktera, inace ispisujemo broj
  523.         if (printStatement.getExpr().struct == Tab.charType)
  524.             Code.put(Code.bprint);
  525.         else
  526.             Code.put(Code.print);
  527.  
  528.     }
  529.  
  530.     @Override
  531.     public void visit(OptPrintNumConstDeclared width){
  532.         Code.load(new Obj(Obj.Con, "", Tab.intType, width.getNumConst(), 0));
  533.     }
  534.  
  535.     @Override
  536.     public void visit(OptPrintNumConstEpsilon width){
  537.         Code.load(new Obj(Obj.Con, "", Tab.intType, 1, 0));
  538.     }
  539.  
  540.  
  541.     @Override
  542.     public void visit(DesignatorStatementAssign assignmentStmt){
  543.         Obj designatorObj = assignmentStmt.getDesignator().obj;
  544.  
  545.  
  546.         storeDesignator(designatorObj);
  547.  
  548.     }
  549.  
  550.     @Override
  551.     public void visit(DesignatorStatementIncrement incrementStmt){
  552.  
  553.         // ukoliko se na steku nalaze array_addr, indeks
  554.         // treba da dupliramo poslednje dve vrednosti na steku
  555.         // jer cemo isti taj element koristiti za skladistenje rezultata
  556.         if (incrementStmt.getDesignator().obj.getKind() == Obj.Elem)
  557.             Code.put(Code.dup2);
  558.  
  559.         // ucitamo prvo staru vrednost elementa
  560.         loadDesignator(incrementStmt.getDesignator().obj);
  561.  
  562.         // ucitamo konstantu 1
  563.         Code.load(num1constObj);
  564.  
  565.         // izvrsimo operaciju sabiranja
  566.         Code.put(Code.add);
  567.  
  568.         // sacuvamo u element niza
  569.         storeDesignator(incrementStmt.getDesignator().obj);
  570.     }
  571.    
  572.     public void visit(DesignatorStatementDecrement decrementStmt){
  573.         // ukoliko se na steku nalaze array_addr, indeks
  574.         // treba da dupliramo poslednje dve vrednosti na steku
  575.         // jer cemo isti taj element koristiti za skladistenje rezultata
  576.         if (decrementStmt.getDesignator().obj.getKind() == Obj.Elem)
  577.             Code.put(Code.dup2);
  578.  
  579.         // ucitamo prvo staru vrednost elementa
  580.         loadDesignator(decrementStmt.getDesignator().obj);
  581.  
  582.         // ucitamo konstantu 1
  583.         Code.load(num1constObj);
  584.  
  585.         // izvrsimo operaciju oduzimanja
  586.         Code.put(Code.sub);
  587.  
  588.         // sacuvamo u element niza
  589.         storeDesignator(decrementStmt.getDesignator().obj);
  590.     }
  591.  
  592.     @Override
  593.     public void visit(IfStart ifStart){
  594.         // stavimo na stek listu za obradu adresa skoka za trenutni if/else/while
  595.         truePatchStack.add(new LinkedList<>());
  596.  
  597.         // isto kao gore, ali za skok ako je uslov netacan if/else/while
  598.         falsePatchStack.add(new LinkedList<>());
  599.  
  600.     }
  601.  
  602.     @Override
  603.     public void visit(IfElseStatement ifElseStatement){
  604.  
  605.         // prepravljamo skok
  606.         Code.fixup(thenJumpPatchStack.pop());
  607.  
  608.         truePatchStack.pop();
  609.         falsePatchStack.pop();
  610.     }
  611.  
  612.     @Override
  613.     public void visit(ElseStart elseStart){
  614.         List<Integer> adrsToPatchList = falsePatchStack.peek();
  615.  
  616.         // treba izaci iz then, znaci treba nam relativni skok na kraj else grane
  617.         Code.putJump(0);
  618.  
  619.         // nakon sto se zavrsi then treba skociti na kraju if/else kontrole toka
  620.         thenJumpPatchStack.push(Code.pc - 2);
  621.  
  622.  
  623.         fixupAddresses(adrsToPatchList);
  624.     }
  625.  
  626.     @Override
  627.     public void visit(IfStatement ifStatement){
  628.  
  629.         List<Integer> adrsToPatchList = falsePatchStack.peek();
  630.  
  631.  
  632.         fixupAddresses(adrsToPatchList);
  633.  
  634.         truePatchStack.pop();
  635.         falsePatchStack.pop();
  636.     }
  637.  
  638.     @Override
  639.     public void visit(ThenStart thenStart){
  640.         // ispravljamo samo TRUE skokove, jer treba da udjemo u then granu
  641.         List<Integer> adrsToPatchlist = truePatchStack.peek();
  642.  
  643.  
  644.         fixupAddresses(adrsToPatchlist);
  645.     }
  646.  
  647.     @Override
  648.     public void visit(DoWhileStatement doWhileStatement){
  649.  
  650.         // stavljamo skok na adresu koja ukazuje na pocetak do/while petlje
  651.         // ovo radimo jer name je poslednja instrukcija false jump
  652.         // stoga ako se nije desio skok treba da se vratimo na pocetak do/while
  653.         Code.putJump(whileBeginStack.peek());
  654.  
  655.         // na kraju treba obraditi sve true i false skokove, kao i break naredbe
  656.  
  657.  
  658.         // za razliku od if/else, ako je skok true, skacemo na pocetak do/while-a
  659.         List<Integer> adrsToPatchList = truePatchStack.pop();
  660.  
  661.         doWhileFixup(adrsToPatchList, whileBeginStack.peek());
  662.  
  663.  
  664.         // kod false skokova, treba da skacemo napred
  665.         fixupAddresses(falsePatchStack.pop());
  666.  
  667.         // i na kraju break
  668.         fixupAddresses(breakStatementAdrStack.pop());
  669.  
  670.         // i sklonimo liste i podatke vezane za najugnjezdeniji do/while
  671.         continueStatementAdrStack.pop();
  672.  
  673.         whileBeginStack.pop();
  674.  
  675.         whileEndStack.pop();
  676.     }
  677.     @Override
  678.     public void visit(DoWhileBegin doWhileBegin){
  679.         // postavljamo na stek trenutnu vrednost PC-a
  680.         // trenutna vrednost PC-a pokazuje na prvu instrukciju
  681.         // u petli
  682.         whileBeginStack.push(Code.pc);
  683.  
  684.         // kreiramo listu adresa za break naredbe
  685.         breakStatementAdrStack.push(new LinkedList<>());
  686.  
  687.         // kreiramo listu adresa za continue naredbe
  688.         continueStatementAdrStack.push(new LinkedList<>());
  689.  
  690.         // napravimo listu za prepravljanje adresa kod skokova
  691.         truePatchStack.push(new LinkedList<>());
  692.  
  693.         // napravimo listu za prepravljanje adresa kod skokova
  694.         falsePatchStack.push(new LinkedList());
  695.  
  696.  
  697.  
  698.     }
  699.  
  700.     @Override
  701.     public void visit(DoWhileEnd doWhileEnd){
  702.         // postavljamo na stek trenutnu vrednost PC-a
  703.         // trenutna vrednost PC-a pokazuje na instrukciju nakon poslednje naredbe
  704.         // u petlji
  705.         whileEndStack.push(Code.pc);
  706.  
  707.  
  708.  
  709.         // treba obraditi sve continue naredbe
  710.         List<Integer> adrsToPatchList = continueStatementAdrStack.peek();
  711.  
  712.         // kod continue uvek skacemo napred
  713.         fixupAddresses(adrsToPatchList);
  714.  
  715.         // obrisemo sve prepravljene adrese
  716.         adrsToPatchList.clear();
  717.     }
  718.  
  719.     @Override
  720.     public void visit(BreakStatement breakStatement){
  721.         // stavimo instrukciju za skok
  722.         Code.putJump(Code.pc);
  723.  
  724.         // ubacimo adresu koju treba prepraviti
  725.         breakStatementAdrStack.peek().add(Code.pc - 2);
  726.     }
  727.  
  728.     @Override
  729.     public void visit(ContinueStatement continueStatement){
  730.         // stavimo instrukciju za skok
  731.         Code.putJump(Code.pc);
  732.  
  733.         // ubacimo adresu koju treba prepraviti
  734.         continueStatementAdrStack.peek().add(Code.pc - 2);
  735.     }
  736.  
  737.     @Override
  738.     public void visit(ReturnStatement returnStatement){
  739.         Code.put(Code.exit);
  740.         Code.put(Code.return_);
  741.     }
  742.  
  743.     @Override
  744.     public void visit(ReadStatement readStatement){
  745.         Obj designatorObj = readStatement.getDesignator().obj;
  746.  
  747.  
  748.         // char i boolean su bajtovski podaci
  749.         if (designatorObj.getType() == Tab.intType)
  750.             Code.put(Code.read);
  751.         else
  752.             Code.put(Code.bread);
  753.  
  754.         // sacuvamo u zeljeni objekat
  755.         storeDesignator(designatorObj);
  756.     }
  757.  
  758.  
  759.  
  760. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement