diff --git a/MiniC/Makefile b/MiniC/Makefile index dcfc04a..64ba2d8 100644 --- a/MiniC/Makefile +++ b/MiniC/Makefile @@ -86,7 +86,9 @@ define CLEAN import glob import os for f in glob.glob("**/tests/**/*.c", recursive=True): - for s in ("{}-{}.s".format(f[:-2], test) for test in ("naive", "smart", "gcc", "all-in-mem")): + files = ["{}-{}.{}".format(f[:-2], test,ext) for test in ("naive", "smart", "gcc", "all-in-mem") for ext in ("s","riscv","pdf")] + files += ["{}.{}.{}.{}".format(f[:-2], funct, test,ext for funct in ("main") for test in ("enterssa","exitssa") for ext in ("dot.pdf","dot") + for s in files: try: os.remove(s) print("Removed {}".format(s)) diff --git a/MiniC/MiniC.g4 b/MiniC/MiniC.g4 index 6592018..a27b112 100644 --- a/MiniC/MiniC.g4 +++ b/MiniC/MiniC.g4 @@ -52,7 +52,7 @@ print_stat expr : MINUS expr #unaryMinusExpr | NOT expr #notExpr - | expr myop=(MULT|DIV|MOD) expr #multiplicativeExpr + | expr myop=(MULT|DIV|MOD) expr #multiplicativeExpr | expr myop=(PLUS|MINUS) expr #additiveExpr | expr myop=(GT|LT|GTEQ|LTEQ) expr #relationalExpr | expr myop=(EQ|NEQ) expr #equalityExpr diff --git a/MiniC/README-codegen.md b/MiniC/README-codegen.md index e6923a0..de3a4bb 100644 --- a/MiniC/README-codegen.md +++ b/MiniC/README-codegen.md @@ -3,23 +3,32 @@ LAB4 (simple code generation), MIF08 / CAP 2022-23 # Authors -YOUR NAME HERE +Samy Avrillon # Contents -TODO for STUDENTS : Say a bit about the code infrastructure ... +Same as the first lab, you did the structure, so i have litle interest in commenting it. # Test design -TODO: explain your tests +- folder *operators* checks all operations on operators (additive, multiplicative, relations, unary minus, boolean) +- *nested{While,For,Ifs}* checks with structures of nested blocks. +- *forTests* and *whileClauseSyntax* tests for the well-execution of for and while loops. +- *testTooManyVariables* tries initializing many variables in order to make the naive allocator fail. # Design choices -TODO: explain your choices. How did you implement boolean not? Did you implement an extension? +Boolean Not has been implemented using an immediate 1 and the opreator xor, even though such operator exists in riscV (see Known bugs). + +I did implement C-like loops with the same system used in the interpreter. # Known bugs -TODO: Bugs and limitations. +There is a lot of RiscV instruction that are not implemented in Lib, and that makes bigger and less readable code (for exemple, slt would be better than blt for integer comparison). + +By design, we always use a jump statement before a label. Otherwise, the CFG linearization fails. This is intended (the missing jump could be added in *prepare_chunk*). + +So, there is one line in *BuildCFG.c* that sould never be executed (that's why the coverage is not 100% complete), when a label is detected as a leader, as the preceding jump will always have been detected as a leader before it. # Checklists @@ -28,30 +37,30 @@ and *tested* with appropriate test cases. ## Code generation -- [ ] Number Atom -- [ ] Boolean Atom -- [ ] Id Atom -- [ ] Additive expression -- [ ] Multiplicative expression -- [ ] UnaryMinus expression -- [ ] Or expression -- [ ] And expression -- [ ] Equality expression -- [ ] Relational expression (! many cases -> many tests) -- [ ] Not expression +- [X] Number Atom +- [X] Boolean Atom +- [X] Id Atom +- [X] Additive expression +- [X] Multiplicative expression +- [X] UnaryMinus expression +- [X] Or expression +- [X] And expression +- [X] Equality expression +- [X] Relational expression (! many cases -> many tests) +- [X] Not expression ## Statements -- [ ] Prog, assignements -- [ ] While -- [ ] Cond Block -- [ ] If -- [ ] Nested ifs -- [ ] Nested whiles +- [X] Prog, assignements +- [X] While +- [X] Cond Block +- [X] If +- [X] Nested ifs +- [X] Nested whiles ## Allocation -- [ ] Naive allocation -- [ ] All in memory allocation -- [ ] Massive tests of memory allocation +- [X] Naive allocation +- [X] All in memory allocation +- [X] Massive tests of memory allocation diff --git a/MiniC/TP03/MiniCTypingVisitor.py b/MiniC/TP03/MiniCTypingVisitor.py index a750cc2..40a44f6 100644 --- a/MiniC/TP03/MiniCTypingVisitor.py +++ b/MiniC/TP03/MiniCTypingVisitor.py @@ -110,7 +110,7 @@ class MiniCTypingVisitor(MiniCVisitor): else: self._raise(ctx,"boolean operator", fstT) else: - self._assertSameType(ctx,"boolean operator", fstT,sndT) + self._raise(ctx,"boolean operator", fstT,sndT) def visitAndExpr(self, ctx): fstT = self.visit(ctx.expr(0)) @@ -121,7 +121,7 @@ class MiniCTypingVisitor(MiniCVisitor): else: self._raise(ctx,"boolean operator", fstT) else: - self._assertSameType(ctx,"boolean operator", fstT,sndT) + self._raise(ctx,"boolean operator", fstT,sndT) def visitEqualityExpr(self, ctx): fstT = self.visit(ctx.expr(0)) @@ -140,7 +140,7 @@ class MiniCTypingVisitor(MiniCVisitor): else: self._raise(ctx, "comparaison operator", fstT) else: - self._assertSameType(ctx,"comparaison operator", fstT,sndT) + self._raise(ctx,"comparaison operator", fstT,sndT) def visitAdditiveExpr(self, ctx): assert ctx.myop is not None @@ -152,9 +152,9 @@ class MiniCTypingVisitor(MiniCVisitor): elif (fstT == BaseType.String and ctx.myop.type == MiniCParser.PLUS): return BaseType.String else: - self._raise(ctx, "additive operands", fstT) + self._raise(ctx, "additive operands", fstT,sndT) else: - self._assertSameType(ctx,"additive operator", fstT,sndT) + self._raise(ctx,"additive operator", fstT,sndT) def visitMultiplicativeExpr(self, ctx): fstT = self.visit(ctx.expr(0)) @@ -165,7 +165,7 @@ class MiniCTypingVisitor(MiniCVisitor): else: return fstT else: - self._assertSameType(ctx,"multiplicative operator", fstT,sndT) + self._raise(ctx,"multiplicative operands", fstT,sndT) def visitNotExpr(self, ctx): fstT = self.visit(ctx.expr()) diff --git a/MiniC/TP03/tests/students/corrected/bad_type01.c b/MiniC/TP03/tests/provided/examples-types/bad_type01.c similarity index 57% rename from MiniC/TP03/tests/students/corrected/bad_type01.c rename to MiniC/TP03/tests/provided/examples-types/bad_type01.c index 39f8e7c..1a84239 100644 --- a/MiniC/TP03/tests/students/corrected/bad_type01.c +++ b/MiniC/TP03/tests/provided/examples-types/bad_type01.c @@ -11,4 +11,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 8 col 6: type mismatch for multiplicative operator: integer and string +// In function main: Line 8 col 6: invalid type for multiplicative operands: integer and string diff --git a/MiniC/TP03/tests/students/corrected/bad_type_bool_bool.c b/MiniC/TP03/tests/provided/examples-types/bad_type_bool_bool.c similarity index 85% rename from MiniC/TP03/tests/students/corrected/bad_type_bool_bool.c rename to MiniC/TP03/tests/provided/examples-types/bad_type_bool_bool.c index e5f3981..be2d14e 100644 --- a/MiniC/TP03/tests/students/corrected/bad_type_bool_bool.c +++ b/MiniC/TP03/tests/provided/examples-types/bad_type_bool_bool.c @@ -6,4 +6,4 @@ int main(){ } // EXITCODE 2 // EXPECTED -// In function main: Line 4 col 14: invalid type for additive operands: boolean +// In function main: Line 4 col 14: invalid type for additive operands: boolean and boolean diff --git a/MiniC/TP03/tests/students/typeErrors/forInitTyping.c b/MiniC/TP03/tests/students/typeErrors/forInitTyping.c index 6ce6769..2ce0d31 100644 --- a/MiniC/TP03/tests/students/typeErrors/forInitTyping.c +++ b/MiniC/TP03/tests/students/typeErrors/forInitTyping.c @@ -11,4 +11,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 6 col 12: type mismatch for additive operator: integer and boolean +// In function main: Line 6 col 12: invalid type for additive operator: integer and boolean diff --git a/MiniC/TP03/tests/students/typeErrors/invalidAdd.c b/MiniC/TP03/tests/students/typeErrors/invalidAdd.c index 13f78f6..fbf023f 100644 --- a/MiniC/TP03/tests/students/typeErrors/invalidAdd.c +++ b/MiniC/TP03/tests/students/typeErrors/invalidAdd.c @@ -11,4 +11,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 8 col 8: invalid type for additive operands: boolean +// In function main: Line 8 col 8: invalid type for additive operands: boolean and boolean diff --git a/MiniC/TP03/tests/students/typeErrors/mismatchAdd.c b/MiniC/TP03/tests/students/typeErrors/mismatchAdd.c index ea7fd8b..a88dc90 100644 --- a/MiniC/TP03/tests/students/typeErrors/mismatchAdd.c +++ b/MiniC/TP03/tests/students/typeErrors/mismatchAdd.c @@ -13,4 +13,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 10 col 8: type mismatch for additive operator: integer and float +// In function main: Line 10 col 8: invalid type for additive operator: integer and float diff --git a/MiniC/TP03/tests/students/typeErrors/mismatchAnd.c b/MiniC/TP03/tests/students/typeErrors/mismatchAnd.c index 972e09e..2850c2a 100644 --- a/MiniC/TP03/tests/students/typeErrors/mismatchAnd.c +++ b/MiniC/TP03/tests/students/typeErrors/mismatchAnd.c @@ -11,4 +11,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 8 col 8: type mismatch for boolean operator: integer and boolean +// In function main: Line 8 col 8: invalid type for boolean operator: integer and boolean diff --git a/MiniC/TP03/tests/students/typeErrors/mismatchComp.c b/MiniC/TP03/tests/students/typeErrors/mismatchComp.c index a4f962a..724a736 100644 --- a/MiniC/TP03/tests/students/typeErrors/mismatchComp.c +++ b/MiniC/TP03/tests/students/typeErrors/mismatchComp.c @@ -19,4 +19,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 16 col 8: type mismatch for comparaison operator: integer and float +// In function main: Line 16 col 8: invalid type for comparaison operator: integer and float diff --git a/MiniC/TP03/tests/students/typeErrors/mismatchMult.c b/MiniC/TP03/tests/students/typeErrors/mismatchMult.c index c04780e..fbab493 100644 --- a/MiniC/TP03/tests/students/typeErrors/mismatchMult.c +++ b/MiniC/TP03/tests/students/typeErrors/mismatchMult.c @@ -13,4 +13,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 10 col 8: type mismatch for multiplicative operator: integer and float +// In function main: Line 10 col 8: invalid type for multiplicative operands: integer and float diff --git a/MiniC/TP03/tests/students/typeErrors/mismatchOr.c b/MiniC/TP03/tests/students/typeErrors/mismatchOr.c index 37a3891..2ea9ee0 100644 --- a/MiniC/TP03/tests/students/typeErrors/mismatchOr.c +++ b/MiniC/TP03/tests/students/typeErrors/mismatchOr.c @@ -11,4 +11,4 @@ int main(){ // EXITCODE 2 // EXPECTED -// In function main: Line 8 col 8: type mismatch for boolean operator: integer and boolean +// In function main: Line 8 col 8: invalid type for boolean operator: integer and boolean diff --git a/MiniC/TP04/AllInMemAllocator.py b/MiniC/TP04/AllInMemAllocator.py index b4ce296..b79fb9d 100644 --- a/MiniC/TP04/AllInMemAllocator.py +++ b/MiniC/TP04/AllInMemAllocator.py @@ -14,12 +14,32 @@ class AllInMemAllocator(Allocator): before: List[Instruction] = [] after: List[Instruction] = [] subst: Dict[Operand, Operand] = {} + + old_args = old_instr.args() + for arg in old_args: + # We substitute + subst[arg] = S[numreg] + numreg += 1 + for arg in old_instr.used(): + # We have to read them from memory + if(isinstance(arg, Temporary)): + before.append(RiscV.ld(subst[arg],self._fdata._pool.get_alloced_loc(arg))) + for arg in old_instr.defined(): + # We have to write them after to memory + if(isinstance(arg, Temporary)): + after.append(RiscV.sd(subst[arg],self._fdata._pool.get_alloced_loc(arg))) + + # TODO (Exercise 7): compute before,after,args. # TODO (Exercise 7): iterate over old_args, check which argument # TODO (Exercise 7): is a temporary (e.g. isinstance(..., Temporary)), # TODO (Exercise 7): and if so, generate ld/sd accordingly. Replace the # TODO (Exercise 7): temporary with S[1], S[2] or S[3] physical registers. - new_instr = old_instr.substitute(subst) + try: + new_instr = old_instr.substitute(subst) + except Exception: + # We have an instruction that doesn't need substitution + return [old_instr] return before + [new_instr] + after def prepare(self): diff --git a/MiniC/TP04/BuildCFG.py b/MiniC/TP04/BuildCFG.py index 7e4d384..ce6e903 100644 --- a/MiniC/TP04/BuildCFG.py +++ b/MiniC/TP04/BuildCFG.py @@ -20,7 +20,14 @@ def find_leaders(instructions: List[CodeStatement]) -> List[int]: last is len(instructions) """ leaders: List[int] = [0] - # TODO fill leaders (Lab4b, Exercise 3) + for i in range(1,len(instructions)): + if(isinstance(instructions[i],AbsoluteJump) or isinstance(instructions[i],ConditionalJump)): + # The block ends here and starts just after + leaders.append(i+1) + elif isinstance(instructions[i],Label) and leaders[-1] != i: + # The block starts here + leaders.append(i) + # Else, ignore # The final "ret" is also a form of jump leaders.append(len(instructions)) return leaders @@ -64,9 +71,19 @@ def prepare_chunk(pre_chunk: List[CodeStatement], fdata: FunctionData) -> tuple[ jump = None inner_statements: List[CodeStatement] = pre_chunk # Extract the first instruction from inner_statements if it is a label, or create a fresh one - raise NotImplementedError() # TODO (Lab4b, Exercise 3) + firstStat = inner_statements.pop(0) + if(isinstance(firstStat, Label)): + label = firstStat + else: + inner_statements = [firstStat]+inner_statements + label = fdata.fresh_label(fdata._name) # Extract the last instruction from inner_statements if it is a jump, or do nothing - raise NotImplementedError() # TODO (Lab4b, Exercise 3) + if(inner_statements != []): + lastStat = inner_statements.pop() + if(isinstance(lastStat, ConditionalJump) or isinstance(lastStat, AbsoluteJump)): + jump = lastStat + else: + inner_statements += [lastStat] # Check that there is no other label or jump left in inner_statements l: List[BlockInstr] = [] for i in inner_statements: diff --git a/MiniC/TP04/LinearizeCFG.py b/MiniC/TP04/LinearizeCFG.py index d3f185e..b38fce1 100644 --- a/MiniC/TP04/LinearizeCFG.py +++ b/MiniC/TP04/LinearizeCFG.py @@ -23,10 +23,32 @@ def linearize(cfg) -> List[Statement]: """ Linearize the given control flow graph as a list of instructions. """ - # TODO (Lab 4b, Exercise 5) l: List[Statement] = [] # Linearized CFG blocks: List[Block] = ordered_blocks_list(cfg) - for j, block in enumerate(blocks): + + labdict = {} + # We make the label dictionary + for j,block in enumerate(blocks): + labdict[block.get_label()] = block + + while blocks != []: + block = blocks[0] + if(l != [] and isinstance(l[-1],AbsoluteJump)): + ll : AbsoluteJump = l[-1] + # We try to find the next jump according to that. + try: + # If we find the instruction + b = labdict[ll.label] + if b in blocks: + # We remove the jump instruction and we select the block to use + l.pop() + block = b + except KeyError: + pass + + # We remove the block we used + blocks.remove(block) + # 1. Add the label of the block to the linearization l.append(block.get_label()) # 2. Add the body of the block to the linearization diff --git a/MiniC/TP04/MiniCCodeGen3AVisitor.py b/MiniC/TP04/MiniCCodeGen3AVisitor.py index ff75196..f26e25e 100644 --- a/MiniC/TP04/MiniCCodeGen3AVisitor.py +++ b/MiniC/TP04/MiniCCodeGen3AVisitor.py @@ -75,7 +75,13 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): def visitBooleanAtom(self, ctx) -> Operands.Temporary: # true is 1 false is 0 - raise NotImplementedError() # TODO (Exercise 5) + dtemp = self._current_function.fdata.fresh_tmp() + if(ctx.getText() == "true"): + val = Operands.Immediate(1) + else: + val = Operands.Immediate(0) + self._current_function.add_instruction(RiscV.li(dtemp,val)) + return dtemp def visitIdAtom(self, ctx) -> Operands.Temporary: try: @@ -97,13 +103,52 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): def visitAdditiveExpr(self, ctx) -> Operands.Temporary: assert ctx.myop is not None - raise NotImplementedError() # TODO (Exercise 2) + if self._debug: + print("additive expression, between:", + Trees.toStringTree(ctx.expr(0), None, self._parser), + "and", + Trees.toStringTree(ctx.expr(1), None, self._parser)) + ltemp = self.visit(ctx.expr(0)) + rtemp = self.visit(ctx.expr(1)) + # Getting a fresh temporary for the result of the opreation + dtemp = self._current_function.fdata.fresh_tmp() + if(ctx.myop.type==MiniCParser.PLUS): + self._current_function.add_instruction(RiscV.add(dtemp,ltemp,rtemp)) + elif(ctx.myop.type==MiniCParser.MINUS): + self._current_function.add_instruction(RiscV.sub(dtemp,ltemp,rtemp)) + else: + raise MiniCInternalError("Unknown additive operator from the parser:",ctx.myop) + return dtemp def visitOrExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError() # TODO (Exercise 5) + if self._debug: + print("or expression, between:", + Trees.toStringTree(ctx.expr(0), None, self._parser), + "and", + Trees.toStringTree(ctx.expr(1), None, self._parser)) + ltemp = self.visit(ctx.expr(0)) + rtemp = self.visit(ctx.expr(1)) + # Getting a fresh temporary for the result of the opreation + # We could do only two instructions with slt + d0temp = self._current_function.fdata.fresh_tmp() + d1temp = self._current_function.fdata.fresh_tmp() + self._current_function.add_instruction(RiscV.add(d0temp,ltemp,rtemp)) + self._current_function.add_instruction(RiscV.mul(d1temp,ltemp,rtemp)) + self._current_function.add_instruction(RiscV.sub(d0temp,d0temp,d1temp)) + return d0temp def visitAndExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError() # TODO (Exercise 5) + if self._debug: + print("or expression, between:", + Trees.toStringTree(ctx.expr(0), None, self._parser), + "and", + Trees.toStringTree(ctx.expr(1), None, self._parser)) + ltemp = self.visit(ctx.expr(0)) + rtemp = self.visit(ctx.expr(1)) + # Getting a fresh temporary for the result of the opreation + dtemp = self._current_function.fdata.fresh_tmp() + self._current_function.add_instruction(RiscV.mul(dtemp,ltemp,rtemp)) + return dtemp def visitEqualityExpr(self, ctx) -> Operands.Temporary: return self.visitRelationalExpr(ctx) @@ -115,18 +160,63 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): print("relational expression:") print(Trees.toStringTree(ctx, None, self._parser)) print("Condition:", c) - raise NotImplementedError() # TODO (Exercise 5) + ltemp = self.visit(ctx.expr(0)) + rtemp = self.visit(ctx.expr(1)) + # Getting a fresh temporary for the result of the opreation + dtemp = self._current_function.fdata.fresh_tmp() + endlabel = self._current_function.fdata.fresh_label("ifverified") + + self._current_function.add_instruction(RiscV.li(dtemp,Operands.Immediate(1))) + self._current_function.add_comment("If the result of the comparison is true, branch") + self._current_function.add_instruction(RiscV.conditional_jump(endlabel,ltemp,Operands.Condition(ctx.myop.type),rtemp)) + self._current_function.add_instruction(RiscV.li(dtemp,Operands.Immediate(0))) + self._current_function.add_instruction(RiscV.jump(endlabel)) + self._current_function.add_label(endlabel) + return dtemp def visitMultiplicativeExpr(self, ctx) -> Operands.Temporary: assert ctx.myop is not None div_by_zero_lbl = self._current_function.fdata.get_label_div_by_zero() - raise NotImplementedError() # TODO (Exercise 8) + + ltemp = self.visit(ctx.expr(0)) + rtemp = self.visit(ctx.expr(1)) + # Getting a fresh temporary for the result of the opreation + dtemp = self._current_function.fdata.fresh_tmp() + + if(ctx.myop.type==MiniCParser.MULT): + self._current_function.add_instruction(RiscV.mul(dtemp,ltemp,rtemp)) + else: + self._current_function.add_instruction(RiscV.conditional_jump(div_by_zero_lbl,rtemp,Operands.Condition('beq'),Operands.ZERO)) + if(ctx.myop.type==MiniCParser.DIV): + self._current_function.add_instruction(RiscV.div(dtemp,ltemp,rtemp)) + elif(ctx.myop.type==MiniCParser.MOD): + self._current_function.add_instruction(RiscV.rem(dtemp,ltemp,rtemp)) + else: + raise MiniCInternalError("Unknown multiplicative operator from the parser:",ctx.myop) + return dtemp def visitNotExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError() # TODO (Exercise 5) + if self._debug: + print("unitary not expression on expression:", + Trees.toStringTree(ctx.expr(), None, self._parser)) + vtemp = self.visit(ctx.expr()) + # Getting a fresh temporary for the result of the opreation + dtemp = self._current_function.fdata.fresh_tmp() + + # (not a) is (1 xor a) + self._current_function.add_instruction(RiscV.li(dtemp,Operands.Immediate(1))) + self._current_function.add_instruction(RiscV.xor(dtemp,dtemp,vtemp)) + return dtemp def visitUnaryMinusExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError("unaryminusexpr") # TODO (Exercise 2) + if self._debug: + print("unitary minus expression on expression:", + Trees.toStringTree(ctx.expr(), None, self._parser)) + vtemp = self.visit(ctx.expr()) + # Getting a fresh temporary for the result of the opreation + dtemp = self._current_function.fdata.fresh_tmp() + self._current_function.add_instruction(RiscV.sub(dtemp,Operands.ZERO,vtemp)) + return dtemp def visitProgRule(self, ctx) -> None: self.visitChildren(ctx) @@ -158,9 +248,25 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): def visitIfStat(self, ctx) -> None: if self._debug: print("if statement") - end_if_label = self._current_function.fdata.fresh_label("end_if") - raise NotImplementedError() # TODO (Exercise 5) - self._current_function.add_label(end_if_label) + + lendif = self._current_function.fdata.fresh_label("endif") + if(ctx.else_block!=None): + lelse = self._current_function.fdata.fresh_label("else") + dval = self.visit(ctx.expr()) + self._current_function.add_instruction(RiscV.conditional_jump(lelse, dval, Operands.Condition('beq'), Operands.ZERO)) + self.visit(ctx.then_block) + self._current_function.add_instruction(RiscV.jump(lendif)) + self._current_function.add_label(lelse) + self.visit(ctx.else_block) + self._current_function.add_instruction(RiscV.jump(lendif)) + self._current_function.add_label(lendif) + else: + dval = self.visit(ctx.expr()) + self._current_function.add_instruction(RiscV.conditional_jump(lendif, dval, Operands.Condition('beq'), Operands.ZERO)) + self.visit(ctx.then_block) + self._current_function.add_instruction(RiscV.jump(lendif)) + self._current_function.add_label(lendif) + def visitWhileStat(self, ctx) -> None: if self._debug: @@ -168,7 +274,37 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): print(Trees.toStringTree(ctx.expr(), None, self._parser)) print("and block is:") print(Trees.toStringTree(ctx.stat_block(), None, self._parser)) - raise NotImplementedError() # TODO (Exercise 5) + ltest = self._current_function.fdata.fresh_label("testcond") + lendwhile = self._current_function.fdata.fresh_label("endwhile") + self._current_function.add_instruction(RiscV.jump(ltest)) + self._current_function.add_label(ltest) + dcond = self.visit(ctx.expr()) + self._current_function.add_instruction(RiscV.conditional_jump(lendwhile, dcond, Operands.Condition('beq'), Operands.ZERO)) + self.visit(ctx.body) + self._current_function.add_instruction(RiscV.jump(ltest)) + self._current_function.add_label(lendwhile) + + def visitForStat(self, ctx): + init_stat = ctx.init_stat + cond = ctx.cond + loop_stat = ctx.loop_stat + body = ctx.stat_block() + + ltest = self._current_function.fdata.fresh_label("testcond") + lendfor = self._current_function.fdata.fresh_label("endfor") + + if(init_stat != None): + self.visit(init_stat) + self._current_function.add_instruction(RiscV.jump(ltest)) + self._current_function.add_label(ltest) + dcond = self.visit(ctx.expr()) + self._current_function.add_instruction(RiscV.conditional_jump(lendfor, dcond, Operands.Condition('beq'), Operands.ZERO)) + self.visit(body) + if(loop_stat != None): + self.visit(loop_stat) + self._current_function.add_instruction(RiscV.jump(ltest)) + self._current_function.add_label(lendfor) + # visit statements def visitPrintlnintStat(self, ctx) -> None: diff --git a/MiniC/TP04/tests/students/forTests.c b/MiniC/TP04/tests/students/forTests.c new file mode 100644 index 0000000..e05c472 --- /dev/null +++ b/MiniC/TP04/tests/students/forTests.c @@ -0,0 +1,32 @@ +#include "printlib.h" + +int main(){ + int x; + + x = 0; + for(;x<4;){ + println_int(x); + x = x+1; + } + x = 69; + for(x=42;false;){ + } + println_int(x); + for(x = 100;x>=4;x = x/2){ + println_int(x+4); + } + return 0; +} + +// EXITCODE 0 +// EXPECTED +// 0 +// 1 +// 2 +// 3 +// 42 +// 104 +// 54 +// 29 +// 16 +// 10 diff --git a/MiniC/TP04/tests/students/nestedFor.c b/MiniC/TP04/tests/students/nestedFor.c new file mode 100644 index 0000000..aa406b4 --- /dev/null +++ b/MiniC/TP04/tests/students/nestedFor.c @@ -0,0 +1,31 @@ +#include "printlib.h" + +int main(){ + int x,y,z,t; + + t = 0; + x = 0; + for(x=0;x<10;x=x+1){ + y = 0; + for(y=0;y<4;){ + t = t + y; + z = 1; + for(z=1;z<13;z=2*z){ + t = t + 1; + } + y = y + 1; + } + for(;y<7;y=y+2){ + t = t + (y/2); + } + } + println_int(x); + println_int(y); + println_int(z); + return 0; +} + +// EXPECTED +// 10 +// 8 +// 16 diff --git a/MiniC/TP04/tests/students/nestedIfs.c b/MiniC/TP04/tests/students/nestedIfs.c new file mode 100644 index 0000000..e72e6b3 --- /dev/null +++ b/MiniC/TP04/tests/students/nestedIfs.c @@ -0,0 +1,48 @@ +#include "printlib.h" + +int main(){ + int x,y,z; + + if (10 == 10) { + println_int(44); + if (10 == 11) { + println_int(75); + } else if (10 == 10) { + println_int(42); + if (9 == 10) { + println_int(12); + } else if (10 == 9) { + println_int(15); + } else { + println_int(13); + } + println_int(19); + } else { + println_int(31); + } + println_int(25); + } else if (10 == 10) { + println_int(2); + } else { + println_int(89); + if (10 == 10) { + println_int(68); + } else if (10 == 10) { + println_int(46); + } else { + println_int(22); + } + println_int(43); + } + println_int(14); + + return 0; +} + +// EXPECTED +// 44 +// 42 +// 13 +// 19 +// 25 +// 14 diff --git a/MiniC/TP04/tests/students/nestedWhile.c b/MiniC/TP04/tests/students/nestedWhile.c new file mode 100644 index 0000000..60622c2 --- /dev/null +++ b/MiniC/TP04/tests/students/nestedWhile.c @@ -0,0 +1,34 @@ +#include "printlib.h" + +int main(){ + int x,y,z,t; + + t = 0; + x = 0; + while(x<10){ + y = 0; + while(y<4){ + t = t + y; + z = 1; + while(z<13){ + t = t + 1; + z = 2 * z; + } + y = y + 1; + } + while(y<7){ + t = t + (y/2); + y = y + 2; + } + x = x + 1; + } + println_int(x); + println_int(y); + println_int(z); + return 0; +} + +// EXPECTED +// 10 +// 8 +// 16 diff --git a/MiniC/TP04/tests/students/operators/relations/testEq.c b/MiniC/TP04/tests/students/operators/relations/testEq.c new file mode 100644 index 0000000..202555e --- /dev/null +++ b/MiniC/TP04/tests/students/operators/relations/testEq.c @@ -0,0 +1,64 @@ +#include "printlib.h" + +int main() { + + // Testing == + if( 11 == 22 ){ + println_int(420); + }else{ + println_int(57); + } + if( -11 == 22 ){ + println_int(420); + }else{ + println_int(58); + } + if( 11 == -22 ){ + println_int(420); + }else{ + println_int(59); + } + if( -11 == -22 ){ + println_int(420); + }else{ + println_int(60); + } + if( 11 == 11 ){ + println_int(61); + }else{ + println_int(420); + } + if( -22 == -22 ){ + println_int(62); + }else{ + println_int(420); + } + if( true == true ){ + println_int(63); + }else{ + println_int(420); + } + if( true == false ){ + println_int(420); + }else{ + println_int(64); + } + if( false == false ){ + println_int(65); + }else{ + println_int(420); + } + + return 0; +} + +// EXPECTED +// 57 +// 58 +// 59 +// 60 +// 61 +// 62 +// 63 +// 64 +// 65 diff --git a/MiniC/TP04/tests/students/operators/relations/testGeq.c b/MiniC/TP04/tests/students/operators/relations/testGeq.c new file mode 100644 index 0000000..dd6a630 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/relations/testGeq.c @@ -0,0 +1,94 @@ +#include "printlib.h" + +int main() { + + // Testing >= + if( 11 >= 22 ){ + println_int(420); + }else{ + println_int(29); + } + if( -11 >= 22 ){ + println_int(420); + }else{ + println_int(30); + } + if( 11 >= -22 ){ + println_int(31); + }else{ + println_int(420); + } + if( -11 >= -22 ){ + println_int(32); + }else{ + println_int(420); + } + if( 22 >= 11 ){ + println_int(33); + }else{ + println_int(420); + } + if( 22 >= -11 ){ + println_int(34); + }else{ + println_int(420); + } + if( -22 >= 11 ){ + println_int(420); + }else{ + println_int(35); + } + if( -22 >= -11 ){ + println_int(420); + }else{ + println_int(36); + } + if( 11 >= 22 ){ + println_int(420); + }else{ + println_int(37); + } + if( -11 >= 22 ){ + println_int(420); + }else{ + println_int(38); + } + if( 11 >= -22 ){ + println_int(39); + }else{ + println_int(420); + } + if( -11 >= -22 ){ + println_int(40); + }else{ + println_int(420); + } + if( 22 >= 22 ){ + println_int(41); + }else{ + println_int(420); + } + if( -22 >= -22 ){ + println_int(42); + }else{ + println_int(420); + } + + return 0; +} + +// EXPECTED +// 29 +// 30 +// 31 +// 32 +// 33 +// 34 +// 35 +// 36 +// 37 +// 38 +// 39 +// 40 +// 41 +// 42 diff --git a/MiniC/TP04/tests/students/operators/relations/testGt.c b/MiniC/TP04/tests/students/operators/relations/testGt.c new file mode 100644 index 0000000..e6d6c6a --- /dev/null +++ b/MiniC/TP04/tests/students/operators/relations/testGt.c @@ -0,0 +1,93 @@ +#include "printlib.h" + +int main() { + + // Testing > + if( 11 > 22 ){ + println_int(420); + }else{ + println_int(43); + } + if( -11 > 22 ){ + println_int(420); + }else{ + println_int(44); + } + if( 11 > -22 ){ + println_int(45); + }else{ + println_int(420); + } + if( -11 > -22 ){ + println_int(46); + }else{ + println_int(420); + } + if( 22 > 11 ){ + println_int(47); + }else{ + println_int(420); + } + if( 22 > -11 ){ + println_int(48); + }else{ + println_int(420); + } + if( -22 > 11 ){ + println_int(420); + }else{ + println_int(49); + } + if( -22 > -11 ){ + println_int(420); + }else{ + println_int(50); + } + if( 11 > 22 ){ + println_int(420); + }else{ + println_int(51); + } + if( -11 > 22 ){ + println_int(420); + }else{ + println_int(52); + } + if( 11 > -22 ){ + println_int(53); + }else{ + println_int(420); + } + if( -11 > -22 ){ + println_int(54); + }else{ + println_int(420); + } + if( 22 > 22 ){ + println_int(420); + }else{ + println_int(55); + } + if( -22 > -22 ){ + println_int(420); + }else{ + println_int(56); + } + return 0; +} + +// EXPECTED +// 43 +// 44 +// 45 +// 46 +// 47 +// 48 +// 49 +// 50 +// 51 +// 52 +// 53 +// 54 +// 55 +// 56 diff --git a/MiniC/TP04/tests/students/operators/relations/testLeq.c b/MiniC/TP04/tests/students/operators/relations/testLeq.c new file mode 100644 index 0000000..7d3f861 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/relations/testLeq.c @@ -0,0 +1,94 @@ +#include "printlib.h" + +int main() { + + // Testing <= + if( 11 <= 22 ){ + println_int(1); + }else{ + println_int(420); + } + if( -11 <= 22 ){ + println_int(2); + }else{ + println_int(420); + } + if( 11 <= -22 ){ + println_int(420); + }else{ + println_int(3); + } + if( -11 <= -22 ){ + println_int(420); + }else{ + println_int(4); + } + if( 22 <= 11 ){ + println_int(420); + }else{ + println_int(5); + } + if( 22 <= -11 ){ + println_int(420); + }else{ + println_int(6); + } + if( -22 <= 11 ){ + println_int(7); + }else{ + println_int(420); + } + if( -22 <= -11 ){ + println_int(8); + }else{ + println_int(420); + } + if( 11 <= 22 ){ + println_int(9); + }else{ + println_int(420); + } + if( -11 <= 22 ){ + println_int(10); + }else{ + println_int(420); + } + if( 11 <= -22 ){ + println_int(420); + }else{ + println_int(11); + } + if( -11 <= -22 ){ + println_int(420); + }else{ + println_int(12); + } + if( 22 <= 22 ){ + println_int(13); + }else{ + println_int(420); + } + if( -22 <= -22 ){ + println_int(14); + }else{ + println_int(420); + } + + return 0; +} + +// EXPECTED +// 1 +// 2 +// 3 +// 4 +// 5 +// 6 +// 7 +// 8 +// 9 +// 10 +// 11 +// 12 +// 13 +// 14 diff --git a/MiniC/TP04/tests/students/operators/relations/testLt.c b/MiniC/TP04/tests/students/operators/relations/testLt.c new file mode 100644 index 0000000..1360b30 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/relations/testLt.c @@ -0,0 +1,94 @@ +#include "printlib.h" + +int main() { + + // Testing < + if( 11 < 22 ){ + println_int(15); + }else{ + println_int(420); + } + if( -11 < 22 ){ + println_int(16); + }else{ + println_int(420); + } + if( 11 < -22 ){ + println_int(420); + }else{ + println_int(17); + } + if( -11 < -22 ){ + println_int(420); + }else{ + println_int(18); + } + if( 22 < 11 ){ + println_int(420); + }else{ + println_int(19); + } + if( 22 < -11 ){ + println_int(420); + }else{ + println_int(20); + } + if( -22 < 11 ){ + println_int(21); + }else{ + println_int(420); + } + if( -22 < -11 ){ + println_int(22); + }else{ + println_int(420); + } + if( 11 < 22 ){ + println_int(23); + }else{ + println_int(420); + } + if( -11 < 22 ){ + println_int(24); + }else{ + println_int(420); + } + if( 11 < -22 ){ + println_int(420); + }else{ + println_int(25); + } + if( -11 < -22 ){ + println_int(420); + }else{ + println_int(26); + } + if( 22 < 22 ){ + println_int(420); + }else{ + println_int(27); + } + if( -22 < -22 ){ + println_int(420); + }else{ + println_int(28); + } + + return 0; +} + +// EXPECTED +// 15 +// 16 +// 17 +// 18 +// 19 +// 20 +// 21 +// 22 +// 23 +// 24 +// 25 +// 26 +// 27 +// 28 diff --git a/MiniC/TP04/tests/students/operators/relations/testNeq.c b/MiniC/TP04/tests/students/operators/relations/testNeq.c new file mode 100644 index 0000000..7904a35 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/relations/testNeq.c @@ -0,0 +1,64 @@ +#include "printlib.h" + +int main() { + + // Testing != + if( 11 != 22 ){ + println_int(66); + }else{ + println_int(420); + } + if( -11 != 22 ){ + println_int(67); + }else{ + println_int(420); + } + if( 11 != -22 ){ + println_int(68); + }else{ + println_int(420); + } + if( -11 != -22 ){ + println_int(69); + }else{ + println_int(420); + } + if( 11 != 11 ){ + println_int(420); + }else{ + println_int(70); + } + if( -22 != -22 ){ + println_int(420); + }else{ + println_int(71); + } + if( true != true ){ + println_int(420); + }else{ + println_int(72); + } + if( true != false ){ + println_int(73); + }else{ + println_int(420); + } + if( false != false ){ + println_int(420); + }else{ + println_int(74); + } + + return 0; +} + +// EXPECTED +// 66 +// 67 +// 68 +// 69 +// 70 +// 71 +// 72 +// 73 +// 74 diff --git a/MiniC/TP04/tests/students/operators/testAddClause.c b/MiniC/TP04/tests/students/operators/testAddClause.c new file mode 100644 index 0000000..50bc64a --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testAddClause.c @@ -0,0 +1,26 @@ +#include "printlib.h" + +int main() { + + int x,y,z; + + x = 12; + y = -21; + z = 14; + + println_int(x + y); + println_int(y + z); + println_int(z + x); + println_int(z + y); + println_int(y + x); + println_int(x + z); + return 0; +} + +// EXPECTED +// -9 +// -7 +// 26 +// -7 +// -9 +// 26 diff --git a/MiniC/TP04/tests/students/operators/testAndClause.c b/MiniC/TP04/tests/students/operators/testAndClause.c new file mode 100644 index 0000000..e6cb58f --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testAndClause.c @@ -0,0 +1,26 @@ +#include "printlib.h" + +int main() { + + bool x,y; + + x = true; + y = false; + + println_bool(x); + println_bool(y); + println_bool(x && x); + println_bool(y && x); + println_bool(x && y); + println_bool(y && y); + + return 0; +} + +// EXPECTED +// 1 +// 0 +// 1 +// 0 +// 0 +// 0 diff --git a/MiniC/TP04/tests/students/operators/testDivClause.c b/MiniC/TP04/tests/students/operators/testDivClause.c new file mode 100644 index 0000000..72d2465 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testDivClause.c @@ -0,0 +1,24 @@ +#include "printlib.h" + +int main() { + + int x,y; + int u,v; + + x = 3; + y = -4; + u = 41; + v = -31; + + println_int(u / x); + println_int(v / x); + println_int(u / y); + println_int(v / y); + return 0; +} + +// EXPECTED +// 13 +// -10 +// -10 +// 7 diff --git a/MiniC/TP04/tests/students/operators/testDivZero.c b/MiniC/TP04/tests/students/operators/testDivZero.c new file mode 100644 index 0000000..5c03d5d --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testDivZero.c @@ -0,0 +1,25 @@ +#include "printlib.h" + +int main() { + + int x,y; + int u,v; + + x = 3; + y = 0; + u = 41; + v = 0; + + println_int(u / x); + println_int(v / x); + println_int(u / y); + println_int(v / y); + return 0; +} + +// EXPECTED +// 13 +// 0 +// Division by 0 +// SKIP TEST EXPECTED +// EXECCODE 1 diff --git a/MiniC/TP04/tests/students/operators/testMinusClause.c b/MiniC/TP04/tests/students/operators/testMinusClause.c new file mode 100644 index 0000000..1c63fe6 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testMinusClause.c @@ -0,0 +1,26 @@ +#include "printlib.h" + +int main() { + + int x,y,z; + + x = 12; + y = -21; + z = 14; + + println_int(x - y); + println_int(y - z); + println_int(z - x); + println_int(z - y); + println_int(y - x); + println_int(x - z); + return 0; +} + +// EXPECTED +// 33 +// -35 +// 2 +// 35 +// -33 +// -2 diff --git a/MiniC/TP04/tests/students/operators/testModClause.c b/MiniC/TP04/tests/students/operators/testModClause.c new file mode 100644 index 0000000..d4a70bf --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testModClause.c @@ -0,0 +1,24 @@ +#include "printlib.h" + +int main() { + + int x,y; + int u,v; + + x = 3; + y = -4; + u = 41; + v = -31; + + println_int(u % x); + println_int(v % x); + println_int(u % y); + println_int(v % y); + return 0; +} + +// EXPECTED +// 2 +// -1 +// 1 +// -3 diff --git a/MiniC/TP04/tests/students/operators/testModZero.c b/MiniC/TP04/tests/students/operators/testModZero.c new file mode 100644 index 0000000..3783dc6 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testModZero.c @@ -0,0 +1,25 @@ +#include "printlib.h" + +int main() { + + int x,y; + int u,v; + + x = 3; + y = 0; + u = 41; + v = 0; + + println_int(u % x); + println_int(v % x); + println_int(u % y); + println_int(v % y); + return 0; +} + +// EXPECTED +// 2 +// 0 +// Division by 0 +// SKIP TEST EXPECTED +// EXECCODE 1 diff --git a/MiniC/TP04/tests/students/operators/testMulClause.c b/MiniC/TP04/tests/students/operators/testMulClause.c new file mode 100644 index 0000000..6ee151a --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testMulClause.c @@ -0,0 +1,31 @@ +#include "printlib.h" + +int main() { + + int x,y,z,t; + + x = 12; + y = -21; + z = 14; + t = -4; + + println_int(x * y); + println_int(y * z); + println_int(z * x); + println_int(y * t); + println_int(z * y); + println_int(y * x); + println_int(x * z); + println_int(t * y); + return 0; +} + +// EXPECTED +// -252 +// -294 +// 168 +// 84 +// -294 +// -252 +// 168 +// 84 diff --git a/MiniC/TP04/tests/students/operators/testNotClause.c b/MiniC/TP04/tests/students/operators/testNotClause.c new file mode 100644 index 0000000..fdc4671 --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testNotClause.c @@ -0,0 +1,22 @@ +#include "printlib.h" + +int main() { + + bool x,y; + + x = true; + y = false; + + println_bool(x); + println_bool(y); + println_bool(!x); + println_bool(!y); + + return 0; +} + +// EXPECTED +// 1 +// 0 +// 0 +// 1 diff --git a/MiniC/TP04/tests/students/operators/testOrClause.c b/MiniC/TP04/tests/students/operators/testOrClause.c new file mode 100644 index 0000000..3f0667a --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testOrClause.c @@ -0,0 +1,26 @@ +#include "printlib.h" + +int main() { + + bool x,y; + + x = true; + y = false; + + println_bool(x); + println_bool(y); + println_bool(x || x); + println_bool(y || x); + println_bool(x || y); + println_bool(y || y); + + return 0; +} + +// EXPECTED +// 1 +// 0 +// 1 +// 1 +// 1 +// 0 diff --git a/MiniC/TP04/tests/students/operators/testUMinusClause.c b/MiniC/TP04/tests/students/operators/testUMinusClause.c new file mode 100644 index 0000000..ace123d --- /dev/null +++ b/MiniC/TP04/tests/students/operators/testUMinusClause.c @@ -0,0 +1,25 @@ +#include "printlib.h" + +int main() { + + int x,y; + + x = 12; + y = -21; + + println_int(x); + println_int(y); + println_int(-x); + println_int(-y); + println_int(x + (-y)); + println_int((-x) - (-y)); + return 0; +} + +// EXPECTED +// 12 +// -21 +// -12 +// 21 +// 33 +// -33 diff --git a/MiniC/TP04/tests/students/testTooManyVariables.c b/MiniC/TP04/tests/students/testTooManyVariables.c new file mode 100644 index 0000000..408e750 --- /dev/null +++ b/MiniC/TP04/tests/students/testTooManyVariables.c @@ -0,0 +1,37 @@ +#include "printlib.h" + +int main() { + + int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z; + + a = 5; + b = 2; + c = a + b; + d = a - b; + e = c + d; + f = d + e; + g = c - e; + h = f + g; + i = h - e; + j = d + g; + k = g + h; + l = c - d; + m = i + j; + n = j + k; + o = k + k; + p = j - e; + q = c + k; + r = d + e; + s = c + b; + t = l - p; + u = d + s; + v = m - r; + w = c + u; + x = k - m; + y = g + r; + z = l + n; + + return 0; +} + +// EXPECTED diff --git a/MiniC/TP04/tests/students/whileClauseSyntax.c b/MiniC/TP04/tests/students/whileClauseSyntax.c new file mode 100644 index 0000000..e4a5a15 --- /dev/null +++ b/MiniC/TP04/tests/students/whileClauseSyntax.c @@ -0,0 +1,22 @@ +#include "printlib.h" + +int main(){ + int x,y,z; + + x = 42; + y = 0; + while(y None: d = queue.pop(0) for b in DF[d]: if b not in has_phi: - # TODO add a phi node in block `b` (Lab 5a, Exercise 4) - raise NotImplementedError("insertPhis") + params : Dict[Label,Operand] = {} + for bi in (set(b.get_in())): + params[bi.get_label()] = var + phi = PhiNode(var,params) + b._phis.append(phi) + queue.append(b) + has_phi.add(b) def rename_block(cfg: CFG, DT: Dict[Block, Set[Block]], renamer: Renamer, b: Block) -> None: @@ -43,18 +48,19 @@ def rename_block(cfg: CFG, DT: Dict[Block, Set[Block]], renamer: Renamer, b: Blo for i in succ._phis: assert (isinstance(i, PhiNode)) i.rename_from(renamer, b.get_label()) - # TODO recursive call(s) of rename_block (Lab 5a, Exercise 5) - + for dtsucc in DT[b]: + rename_block(cfg,DT,renamer, dtsucc) def rename_variables(cfg: CFG, DT: Dict[Block, Set[Block]]) -> None: """ Rename variables in the CFG, to transform `temp_x = φ(temp_x, ..., temp_x)` - into `temp_x = φ(temp_0, ... temp_n)`. + into `temp_x = φ(temp_0, ..., temp_n)`. This is an helper function called during SSA entry. """ renamer = Renamer(cfg.fdata._pool) - # TODO initial call(s) to rename_block (Lab 5a, Exercise 5) + for etr in cfg.get_entries(): + rename_block(cfg,DT,renamer,etr) def enter_ssa(cfg: CFG, dom_graphs=False, basename="prog") -> None: @@ -66,5 +72,9 @@ def enter_ssa(cfg: CFG, dom_graphs=False, basename="prog") -> None: `dom_graphs` indicates if we have to print the domination graphs. `basename` is used for the names of the produced graphs. """ - # TODO implement this function (Lab 5a, Exercise 2) - raise NotImplementedError("enter_ssa") + # Compute the DF + dom = computeDom(cfg) + dt = computeDT(cfg,dom,dom_graphs,basename) + df = computeDF(cfg,dom,dt,dom_graphs, basename) + insertPhis(cfg,df) + rename_variables(cfg,dt) diff --git a/MiniC/TP05/ExitSSA.py b/MiniC/TP05/ExitSSA.py index 5b385d5..c319a13 100644 --- a/MiniC/TP05/ExitSSA.py +++ b/MiniC/TP05/ExitSSA.py @@ -4,6 +4,7 @@ Functions to convert a CFG out of SSA Form. """ from typing import cast, List, Set, Tuple +from Lib.Errors import MiniCInternalError from Lib import RiscV from Lib.Graphes import DiGraph from Lib.CFG import Block, BlockInstr, CFG @@ -24,8 +25,10 @@ def generate_moves_from_phis(phis: List[PhiNode], parent: Block) -> List[BlockIn This is an helper function called during SSA exit. """ moves: List[BlockInstr] = [] - # TODO compute 'moves', a list of 'mv' instructions to insert under parent - # (Lab 5a, Exercise 6) + plabel = parent.get_label() + for phi in phis: + if(plabel in phi.used()): + moves.append(RiscV.mv(phi.var,phi.used()[plabel])) return moves @@ -38,11 +41,34 @@ def exit_ssa(cfg: CFG, is_smart: bool) -> None: for b in cfg.get_blocks(): phis = cast(List[PhiNode], b._phis) # Use cast for Pyright b._phis = [] # Remove all phi nodes in the block + blabel = b.get_label() parents: List[Block] = b.get_in().copy() # Copy as we modify it by adding blocks - for parent in parents: - moves = generate_moves_from_phis(phis, parent) - # TODO Add the block containing 'moves' to 'cfg' - # and update edges and jumps accordingly (Lab 5a, Exercise 6) - raise NotImplementedError("exit_ssa") - + for p in parents: + moves = generate_moves_from_phis(phis, p) + if(len(moves)==0): + continue + # Creating the block + ilabel = cfg.fdata.fresh_label(p.get_label().name+"_to_"+b.get_label().name) + i = Block(ilabel,moves,AbsoluteJump(blabel)) + # Add the block + cfg.add_block(i) + # Changing the jumps + ot = p.get_terminator() + if(isinstance(ot,BranchingTerminator)): + if(ot.label_then == blabel): + ot.label_then = ilabel + if(ot.label_else == blabel): + ot.label_else = ilabel + elif(isinstance(ot,AbsoluteJump)): + assert(ot.label == blabel) + ot = AbsoluteJump(ilabel) + elif(isinstance(ot,Return)): + raise MiniCInternalError("Malformed CFG, cannot have a return in a parent block") + else: + raise MiniCInternalError("I don't know of this terminator type:",type(ot)) + p.set_terminator(ot) # This instruction might be useless + # Moving from p -> b to p -> i -> b + cfg.remove_edge(p,b) + cfg.add_edge(p,i) + cfg.add_edge(i,b) diff --git a/TP01/riscv/ex1.riscv b/TP01/riscv/ex1.riscv new file mode 100755 index 0000000..5959395 Binary files /dev/null and b/TP01/riscv/ex1.riscv differ diff --git a/TP01/riscv/libprint.o b/TP01/riscv/libprint.o new file mode 100644 index 0000000..94ea068 Binary files /dev/null and b/TP01/riscv/libprint.o differ diff --git a/TP01/riscv/test_print b/TP01/riscv/test_print new file mode 100755 index 0000000..5d8a5c5 Binary files /dev/null and b/TP01/riscv/test_print differ diff --git a/TP01/riscv/test_print.o b/TP01/riscv/test_print.o new file mode 100644 index 0000000..e6f3eb6 Binary files /dev/null and b/TP01/riscv/test_print.o differ diff --git a/TP01/riscv/test_print.riscv b/TP01/riscv/test_print.riscv new file mode 100755 index 0000000..8136e2b Binary files /dev/null and b/TP01/riscv/test_print.riscv differ diff --git a/TP02/ariteval/AritLexer.py b/TP02/ariteval/AritLexer.py new file mode 100644 index 0000000..71ecfde --- /dev/null +++ b/TP02/ariteval/AritLexer.py @@ -0,0 +1,77 @@ +# Generated from Arit.g4 by ANTLR 4.9.2 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +# header - mettre les d??clarations globales +import sys +idTab = {}; + +class UnknownIdentifier(Exception): + pass + +class DivByZero(Exception): + pass + + + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\6") + buf.write("\'\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\3\2\3\2\3\2\3\2") + buf.write("\7\2\20\n\2\f\2\16\2\23\13\2\3\2\3\2\3\3\6\3\30\n\3\r") + buf.write("\3\16\3\31\3\4\6\4\35\n\4\r\4\16\4\36\3\5\6\5\"\n\5\r") + buf.write("\5\16\5#\3\5\3\5\2\2\6\3\3\5\4\7\5\t\6\3\2\5\4\2\f\f\17") + buf.write("\17\4\2C\\c|\5\2\13\f\17\17\"\"\2*\2\3\3\2\2\2\2\5\3\2") + buf.write("\2\2\2\7\3\2\2\2\2\t\3\2\2\2\3\13\3\2\2\2\5\27\3\2\2\2") + buf.write("\7\34\3\2\2\2\t!\3\2\2\2\13\f\7\61\2\2\f\r\7\61\2\2\r") + buf.write("\21\3\2\2\2\16\20\n\2\2\2\17\16\3\2\2\2\20\23\3\2\2\2") + buf.write("\21\17\3\2\2\2\21\22\3\2\2\2\22\24\3\2\2\2\23\21\3\2\2") + buf.write("\2\24\25\b\2\2\2\25\4\3\2\2\2\26\30\t\3\2\2\27\26\3\2") + buf.write("\2\2\30\31\3\2\2\2\31\27\3\2\2\2\31\32\3\2\2\2\32\6\3") + buf.write("\2\2\2\33\35\4\62;\2\34\33\3\2\2\2\35\36\3\2\2\2\36\34") + buf.write("\3\2\2\2\36\37\3\2\2\2\37\b\3\2\2\2 \"\t\4\2\2! \3\2\2") + buf.write("\2\"#\3\2\2\2#!\3\2\2\2#$\3\2\2\2$%\3\2\2\2%&\b\5\2\2") + buf.write("&\n\3\2\2\2\7\2\21\31\36#\3\b\2\2") + return buf.getvalue() + + +class AritLexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + COMMENT = 1 + ID = 2 + INT = 3 + WS = 4 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + ] + + symbolicNames = [ "", + "COMMENT", "ID", "INT", "WS" ] + + ruleNames = [ "COMMENT", "ID", "INT", "WS" ] + + grammarFileName = "Arit.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/TP02/ariteval/AritListener.py b/TP02/ariteval/AritListener.py new file mode 100644 index 0000000..d1ddd11 --- /dev/null +++ b/TP02/ariteval/AritListener.py @@ -0,0 +1,33 @@ +# Generated from Arit.g4 by ANTLR 4.9.2 +from antlr4 import * +if __name__ is not None and "." in __name__: + from .AritParser import AritParser +else: + from AritParser import AritParser + +# header - mettre les d??clarations globales +import sys +idTab = {}; + +class UnknownIdentifier(Exception): + pass + +class DivByZero(Exception): + pass + + + +# This class defines a complete listener for a parse tree produced by AritParser. +class AritListener(ParseTreeListener): + + # Enter a parse tree produced by AritParser#prog. + def enterProg(self, ctx:AritParser.ProgContext): + pass + + # Exit a parse tree produced by AritParser#prog. + def exitProg(self, ctx:AritParser.ProgContext): + pass + + + +del AritParser \ No newline at end of file diff --git a/TP02/ariteval/AritParser.py b/TP02/ariteval/AritParser.py new file mode 100644 index 0000000..369e7b4 --- /dev/null +++ b/TP02/ariteval/AritParser.py @@ -0,0 +1,110 @@ +# Generated from Arit.g4 by ANTLR 4.9.2 +# encoding: utf-8 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +# header - mettre les d??clarations globales +import sys +idTab = {}; + +class UnknownIdentifier(Exception): + pass + +class DivByZero(Exception): + pass + + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\6") + buf.write("\b\4\2\t\2\3\2\3\2\3\2\3\2\2\2\3\2\2\2\2\6\2\4\3\2\2\2") + buf.write("\4\5\7\4\2\2\5\6\b\2\1\2\6\3\3\2\2\2\2") + return buf.getvalue() + + +class AritParser ( Parser ): + + grammarFileName = "Arit.g4" + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + sharedContextCache = PredictionContextCache() + + literalNames = [ ] + + symbolicNames = [ "", "COMMENT", "ID", "INT", "WS" ] + + RULE_prog = 0 + + ruleNames = [ "prog" ] + + EOF = Token.EOF + COMMENT=1 + ID=2 + INT=3 + WS=4 + + def __init__(self, input:TokenStream, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache) + self._predicates = None + + + + + class ProgContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self._ID = None # Token + + def ID(self): + return self.getToken(AritParser.ID, 0) + + def getRuleIndex(self): + return AritParser.RULE_prog + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterProg" ): + listener.enterProg(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitProg" ): + listener.exitProg(self) + + + + + def prog(self): + + localctx = AritParser.ProgContext(self, self._ctx, self.state) + self.enterRule(localctx, 0, self.RULE_prog) + try: + self.enterOuterAlt(localctx, 1) + self.state = 2 + localctx._ID = self.match(AritParser.ID) + print("prog = "+str((None if localctx._ID is None else localctx._ID.text))); + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + + + diff --git a/TP02/ariteval/tree.dot b/TP02/ariteval/tree.dot new file mode 100644 index 0000000..7e64e30 --- /dev/null +++ b/TP02/ariteval/tree.dot @@ -0,0 +1,5 @@ +digraph { + 139921865517408 [label=prog] + 139921863565696 [label=Hello] + 139921865517408 -> 139921863565696 +} diff --git a/TP02/ariteval/tree.dot.pdf b/TP02/ariteval/tree.dot.pdf new file mode 100644 index 0000000..f52b906 Binary files /dev/null and b/TP02/ariteval/tree.dot.pdf differ diff --git a/TP02/demo_files/ex1/Example1.py b/TP02/demo_files/ex1/Example1.py new file mode 100644 index 0000000..bdc667e --- /dev/null +++ b/TP02/demo_files/ex1/Example1.py @@ -0,0 +1,69 @@ +# Generated from Example1.g4 by ANTLR 4.9.2 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\t") + buf.write("*\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7") + buf.write("\4\b\t\b\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\5\7\5\33\n") + buf.write("\5\f\5\16\5\36\13\5\3\6\6\6!\n\6\r\6\16\6\"\3\6\3\6\3") + buf.write("\7\3\7\3\b\3\b\2\2\t\3\3\5\4\7\5\t\6\13\7\r\b\17\t\3\2") + buf.write("\6\5\2,-//\61\61\3\2\62;\4\2C\\c|\5\2\13\f\17\17\"\"\2") + buf.write(",\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13") + buf.write("\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\3\21\3\2\2\2\5\23\3") + buf.write("\2\2\2\7\25\3\2\2\2\t\27\3\2\2\2\13 \3\2\2\2\r&\3\2\2") + buf.write("\2\17(\3\2\2\2\21\22\t\2\2\2\22\4\3\2\2\2\23\24\t\3\2") + buf.write("\2\24\6\3\2\2\2\25\26\t\4\2\2\26\b\3\2\2\2\27\34\5\7\4") + buf.write("\2\30\33\5\7\4\2\31\33\5\5\3\2\32\30\3\2\2\2\32\31\3\2") + buf.write("\2\2\33\36\3\2\2\2\34\32\3\2\2\2\34\35\3\2\2\2\35\n\3") + buf.write("\2\2\2\36\34\3\2\2\2\37!\t\5\2\2 \37\3\2\2\2!\"\3\2\2") + buf.write("\2\" \3\2\2\2\"#\3\2\2\2#$\3\2\2\2$%\b\6\2\2%\f\3\2\2") + buf.write("\2&\'\7*\2\2\'\16\3\2\2\2()\7+\2\2)\20\3\2\2\2\6\2\32") + buf.write("\34\"\3\b\2\2") + return buf.getvalue() + + +class Example1(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + OP = 1 + DIGIT = 2 + LETTER = 3 + ID = 4 + WS = 5 + OPENP = 6 + ENDP = 7 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "'('", "')'" ] + + symbolicNames = [ "", + "OP", "DIGIT", "LETTER", "ID", "WS", "OPENP", "ENDP" ] + + ruleNames = [ "OP", "DIGIT", "LETTER", "ID", "WS", "OPENP", "ENDP" ] + + grammarFileName = "Example1.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/TP02/demo_files/ex2/Example2Lexer.py b/TP02/demo_files/ex2/Example2Lexer.py new file mode 100644 index 0000000..f748f70 --- /dev/null +++ b/TP02/demo_files/ex2/Example2Lexer.py @@ -0,0 +1,64 @@ +# Generated from Example2.g4 by ANTLR 4.9.2 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\7") + buf.write("\"\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\3\2\3\2") + buf.write("\3\3\3\3\3\4\6\4\23\n\4\r\4\16\4\24\3\5\6\5\30\n\5\r\5") + buf.write("\16\5\31\3\6\6\6\35\n\6\r\6\16\6\36\3\6\3\6\2\2\7\3\3") + buf.write("\5\4\7\5\t\6\13\7\3\2\5\5\2,-//\61\61\4\2C\\c|\5\2\13") + buf.write("\f\17\17\"\"\2$\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2") + buf.write("\t\3\2\2\2\2\13\3\2\2\2\3\r\3\2\2\2\5\17\3\2\2\2\7\22") + buf.write("\3\2\2\2\t\27\3\2\2\2\13\34\3\2\2\2\r\16\7=\2\2\16\4\3") + buf.write("\2\2\2\17\20\t\2\2\2\20\6\3\2\2\2\21\23\4\62;\2\22\21") + buf.write("\3\2\2\2\23\24\3\2\2\2\24\22\3\2\2\2\24\25\3\2\2\2\25") + buf.write("\b\3\2\2\2\26\30\t\3\2\2\27\26\3\2\2\2\30\31\3\2\2\2\31") + buf.write("\27\3\2\2\2\31\32\3\2\2\2\32\n\3\2\2\2\33\35\t\4\2\2\34") + buf.write("\33\3\2\2\2\35\36\3\2\2\2\36\34\3\2\2\2\36\37\3\2\2\2") + buf.write("\37 \3\2\2\2 !\b\6\2\2!\f\3\2\2\2\6\2\24\31\36\3\b\2\2") + return buf.getvalue() + + +class Example2Lexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + T__0 = 1 + OP = 2 + INT = 3 + ID = 4 + WS = 5 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "';'" ] + + symbolicNames = [ "", + "OP", "INT", "ID", "WS" ] + + ruleNames = [ "T__0", "OP", "INT", "ID", "WS" ] + + grammarFileName = "Example2.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/TP02/demo_files/ex2/Example2Listener.py b/TP02/demo_files/ex2/Example2Listener.py new file mode 100644 index 0000000..602afd1 --- /dev/null +++ b/TP02/demo_files/ex2/Example2Listener.py @@ -0,0 +1,30 @@ +# Generated from Example2.g4 by ANTLR 4.9.2 +from antlr4 import * +if __name__ is not None and "." in __name__: + from .Example2Parser import Example2Parser +else: + from Example2Parser import Example2Parser + +# This class defines a complete listener for a parse tree produced by Example2Parser. +class Example2Listener(ParseTreeListener): + + # Enter a parse tree produced by Example2Parser#full_expr. + def enterFull_expr(self, ctx:Example2Parser.Full_exprContext): + pass + + # Exit a parse tree produced by Example2Parser#full_expr. + def exitFull_expr(self, ctx:Example2Parser.Full_exprContext): + pass + + + # Enter a parse tree produced by Example2Parser#expr. + def enterExpr(self, ctx:Example2Parser.ExprContext): + pass + + # Exit a parse tree produced by Example2Parser#expr. + def exitExpr(self, ctx:Example2Parser.ExprContext): + pass + + + +del Example2Parser \ No newline at end of file diff --git a/TP02/demo_files/ex2/Example2Parser.py b/TP02/demo_files/ex2/Example2Parser.py new file mode 100644 index 0000000..2e8beb2 --- /dev/null +++ b/TP02/demo_files/ex2/Example2Parser.py @@ -0,0 +1,221 @@ +# Generated from Example2.g4 by ANTLR 4.9.2 +# encoding: utf-8 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\7") + buf.write("\31\4\2\t\2\4\3\t\3\3\2\3\2\3\2\3\2\3\3\3\3\3\3\3\3\5") + buf.write("\3\17\n\3\3\3\3\3\3\3\7\3\24\n\3\f\3\16\3\27\13\3\3\3") + buf.write("\2\3\4\4\2\4\2\2\2\30\2\6\3\2\2\2\4\16\3\2\2\2\6\7\5\4") + buf.write("\3\2\7\b\7\3\2\2\b\t\7\2\2\3\t\3\3\2\2\2\n\13\b\3\1\2") + buf.write("\13\f\7\6\2\2\f\17\b\3\1\2\r\17\7\5\2\2\16\n\3\2\2\2\16") + buf.write("\r\3\2\2\2\17\25\3\2\2\2\20\21\f\5\2\2\21\22\7\4\2\2\22") + buf.write("\24\5\4\3\6\23\20\3\2\2\2\24\27\3\2\2\2\25\23\3\2\2\2") + buf.write("\25\26\3\2\2\2\26\5\3\2\2\2\27\25\3\2\2\2\4\16\25") + return buf.getvalue() + + +class Example2Parser ( Parser ): + + grammarFileName = "Example2.g4" + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + sharedContextCache = PredictionContextCache() + + literalNames = [ "", "';'" ] + + symbolicNames = [ "", "", "OP", "INT", "ID", "WS" ] + + RULE_full_expr = 0 + RULE_expr = 1 + + ruleNames = [ "full_expr", "expr" ] + + EOF = Token.EOF + T__0=1 + OP=2 + INT=3 + ID=4 + WS=5 + + def __init__(self, input:TokenStream, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache) + self._predicates = None + + + + + class Full_exprContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + def expr(self): + return self.getTypedRuleContext(Example2Parser.ExprContext,0) + + + def EOF(self): + return self.getToken(Example2Parser.EOF, 0) + + def getRuleIndex(self): + return Example2Parser.RULE_full_expr + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterFull_expr" ): + listener.enterFull_expr(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitFull_expr" ): + listener.exitFull_expr(self) + + + + + def full_expr(self): + + localctx = Example2Parser.Full_exprContext(self, self._ctx, self.state) + self.enterRule(localctx, 0, self.RULE_full_expr) + try: + self.enterOuterAlt(localctx, 1) + self.state = 4 + self.expr(0) + self.state = 5 + self.match(Example2Parser.T__0) + self.state = 6 + self.match(Example2Parser.EOF) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + class ExprContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + self._ID = None # Token + + def ID(self): + return self.getToken(Example2Parser.ID, 0) + + def INT(self): + return self.getToken(Example2Parser.INT, 0) + + def expr(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(Example2Parser.ExprContext) + else: + return self.getTypedRuleContext(Example2Parser.ExprContext,i) + + + def OP(self): + return self.getToken(Example2Parser.OP, 0) + + def getRuleIndex(self): + return Example2Parser.RULE_expr + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterExpr" ): + listener.enterExpr(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitExpr" ): + listener.exitExpr(self) + + + + def expr(self, _p:int=0): + _parentctx = self._ctx + _parentState = self.state + localctx = Example2Parser.ExprContext(self, self._ctx, _parentState) + _prevctx = localctx + _startState = 2 + self.enterRecursionRule(localctx, 2, self.RULE_expr, _p) + try: + self.enterOuterAlt(localctx, 1) + self.state = 12 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [Example2Parser.ID]: + self.state = 9 + localctx._ID = self.match(Example2Parser.ID) + print('oh an id : '+(None if localctx._ID is None else localctx._ID.text)) + pass + elif token in [Example2Parser.INT]: + self.state = 11 + self.match(Example2Parser.INT) + pass + else: + raise NoViableAltException(self) + + self._ctx.stop = self._input.LT(-1) + self.state = 19 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,1,self._ctx) + while _alt!=2 and _alt!=ATN.INVALID_ALT_NUMBER: + if _alt==1: + if self._parseListeners is not None: + self.triggerExitRuleEvent() + _prevctx = localctx + localctx = Example2Parser.ExprContext(self, _parentctx, _parentState) + self.pushNewRecursionContext(localctx, _startState, self.RULE_expr) + self.state = 14 + if not self.precpred(self._ctx, 3): + from antlr4.error.Errors import FailedPredicateException + raise FailedPredicateException(self, "self.precpred(self._ctx, 3)") + self.state = 15 + self.match(Example2Parser.OP) + self.state = 16 + self.expr(4) + self.state = 21 + self._errHandler.sync(self) + _alt = self._interp.adaptivePredict(self._input,1,self._ctx) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.unrollRecursionContexts(_parentctx) + return localctx + + + + def sempred(self, localctx:RuleContext, ruleIndex:int, predIndex:int): + if self._predicates == None: + self._predicates = dict() + self._predicates[1] = self.expr_sempred + pred = self._predicates.get(ruleIndex, None) + if pred is None: + raise Exception("No predicate with index:" + str(ruleIndex)) + else: + return pred(localctx, predIndex) + + def expr_sempred(self, localctx:ExprContext, predIndex:int): + if predIndex == 0: + return self.precpred(self._ctx, 3) + + + + + diff --git a/TP03/tree/Makefile b/TP03/tree/Makefile new file mode 100644 index 0000000..027b338 --- /dev/null +++ b/TP03/tree/Makefile @@ -0,0 +1,18 @@ +PACKAGE = Tree +MAINFILE = tree + +ifndef ANTLR4 +abort: + $(error variable ANTLR4 is not set) +endif + +all: $(PACKAGE).g4 + $(ANTLR4) $^ -Dlanguage=Python3 -visitor + +run: $(MAINFILE).py + python3 $^ + + +clean: + find . \( -iname "~" -or -iname "*.cache*" -or -iname "*.diff" -or -iname "log.txt" -or -iname "*.pyc" -or -iname "*.tokens" -or -iname "*.interp" \) -exec rm -rf '{}' \; + rm -rf $(PACKAGE)*.py diff --git a/TP03/tree/TreeLexer.py b/TP03/tree/TreeLexer.py new file mode 100644 index 0000000..1e045b1 --- /dev/null +++ b/TP03/tree/TreeLexer.py @@ -0,0 +1,60 @@ +# Generated from Tree.g4 by ANTLR 4.9.2 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2\6") + buf.write("\33\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\3\2\3\2\3\3\3") + buf.write("\3\3\4\6\4\21\n\4\r\4\16\4\22\3\5\6\5\26\n\5\r\5\16\5") + buf.write("\27\3\5\3\5\2\2\6\3\3\5\4\7\5\t\6\3\2\4\3\2\62;\4\2\13") + buf.write("\f\"\"\2\34\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3") + buf.write("\2\2\2\3\13\3\2\2\2\5\r\3\2\2\2\7\20\3\2\2\2\t\25\3\2") + buf.write("\2\2\13\f\7*\2\2\f\4\3\2\2\2\r\16\7+\2\2\16\6\3\2\2\2") + buf.write("\17\21\t\2\2\2\20\17\3\2\2\2\21\22\3\2\2\2\22\20\3\2\2") + buf.write("\2\22\23\3\2\2\2\23\b\3\2\2\2\24\26\t\3\2\2\25\24\3\2") + buf.write("\2\2\26\27\3\2\2\2\27\25\3\2\2\2\27\30\3\2\2\2\30\31\3") + buf.write("\2\2\2\31\32\b\5\2\2\32\n\3\2\2\2\5\2\22\27\3\b\2\2") + return buf.getvalue() + + +class TreeLexer(Lexer): + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + T__0 = 1 + T__1 = 2 + INT = 3 + WS = 4 + + channelNames = [ u"DEFAULT_TOKEN_CHANNEL", u"HIDDEN" ] + + modeNames = [ "DEFAULT_MODE" ] + + literalNames = [ "", + "'('", "')'" ] + + symbolicNames = [ "", + "INT", "WS" ] + + ruleNames = [ "T__0", "T__1", "INT", "WS" ] + + grammarFileName = "Tree.g4" + + def __init__(self, input=None, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache()) + self._actions = None + self._predicates = None + + diff --git a/TP03/tree/TreeListener.py b/TP03/tree/TreeListener.py new file mode 100644 index 0000000..17451a7 --- /dev/null +++ b/TP03/tree/TreeListener.py @@ -0,0 +1,39 @@ +# Generated from Tree.g4 by ANTLR 4.9.2 +from antlr4 import * +if __name__ is not None and "." in __name__: + from .TreeParser import TreeParser +else: + from TreeParser import TreeParser + +# This class defines a complete listener for a parse tree produced by TreeParser. +class TreeListener(ParseTreeListener): + + # Enter a parse tree produced by TreeParser#top. + def enterTop(self, ctx:TreeParser.TopContext): + pass + + # Exit a parse tree produced by TreeParser#top. + def exitTop(self, ctx:TreeParser.TopContext): + pass + + + # Enter a parse tree produced by TreeParser#leaf. + def enterLeaf(self, ctx:TreeParser.LeafContext): + pass + + # Exit a parse tree produced by TreeParser#leaf. + def exitLeaf(self, ctx:TreeParser.LeafContext): + pass + + + # Enter a parse tree produced by TreeParser#node. + def enterNode(self, ctx:TreeParser.NodeContext): + pass + + # Exit a parse tree produced by TreeParser#node. + def exitNode(self, ctx:TreeParser.NodeContext): + pass + + + +del TreeParser \ No newline at end of file diff --git a/TP03/tree/TreeParser.py b/TP03/tree/TreeParser.py new file mode 100644 index 0000000..a1d5b1b --- /dev/null +++ b/TP03/tree/TreeParser.py @@ -0,0 +1,247 @@ +# Generated from Tree.g4 by ANTLR 4.9.2 +# encoding: utf-8 +from antlr4 import * +from io import StringIO +import sys +if sys.version_info[1] > 5: + from typing import TextIO +else: + from typing.io import TextIO + + +def serializedATN(): + with StringIO() as buf: + buf.write("\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\6") + buf.write("\26\4\2\t\2\4\3\t\3\3\2\3\2\3\2\3\3\3\3\3\3\3\3\6\3\16") + buf.write("\n\3\r\3\16\3\17\3\3\3\3\5\3\24\n\3\3\3\2\2\4\2\4\2\2") + buf.write("\2\25\2\6\3\2\2\2\4\23\3\2\2\2\6\7\5\4\3\2\7\b\7\2\2\3") + buf.write("\b\3\3\2\2\2\t\24\7\5\2\2\n\13\7\3\2\2\13\r\7\5\2\2\f") + buf.write("\16\5\4\3\2\r\f\3\2\2\2\16\17\3\2\2\2\17\r\3\2\2\2\17") + buf.write("\20\3\2\2\2\20\21\3\2\2\2\21\22\7\4\2\2\22\24\3\2\2\2") + buf.write("\23\t\3\2\2\2\23\n\3\2\2\2\24\5\3\2\2\2\4\17\23") + return buf.getvalue() + + +class TreeParser ( Parser ): + + grammarFileName = "Tree.g4" + + atn = ATNDeserializer().deserialize(serializedATN()) + + decisionsToDFA = [ DFA(ds, i) for i, ds in enumerate(atn.decisionToState) ] + + sharedContextCache = PredictionContextCache() + + literalNames = [ "", "'('", "')'" ] + + symbolicNames = [ "", "", "", "INT", "WS" ] + + RULE_int_tree_top = 0 + RULE_int_tree = 1 + + ruleNames = [ "int_tree_top", "int_tree" ] + + EOF = Token.EOF + T__0=1 + T__1=2 + INT=3 + WS=4 + + def __init__(self, input:TokenStream, output:TextIO = sys.stdout): + super().__init__(input, output) + self.checkVersion("4.9.2") + self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache) + self._predicates = None + + + + + class Int_tree_topContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + + def getRuleIndex(self): + return TreeParser.RULE_int_tree_top + + + def copyFrom(self, ctx:ParserRuleContext): + super().copyFrom(ctx) + + + + class TopContext(Int_tree_topContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a TreeParser.Int_tree_topContext + super().__init__(parser) + self.copyFrom(ctx) + + def int_tree(self): + return self.getTypedRuleContext(TreeParser.Int_treeContext,0) + + def EOF(self): + return self.getToken(TreeParser.EOF, 0) + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterTop" ): + listener.enterTop(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitTop" ): + listener.exitTop(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitTop" ): + return visitor.visitTop(self) + else: + return visitor.visitChildren(self) + + + + def int_tree_top(self): + + localctx = TreeParser.Int_tree_topContext(self, self._ctx, self.state) + self.enterRule(localctx, 0, self.RULE_int_tree_top) + try: + localctx = TreeParser.TopContext(self, localctx) + self.enterOuterAlt(localctx, 1) + self.state = 4 + self.int_tree() + self.state = 5 + self.match(TreeParser.EOF) + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + class Int_treeContext(ParserRuleContext): + __slots__ = 'parser' + + def __init__(self, parser, parent:ParserRuleContext=None, invokingState:int=-1): + super().__init__(parent, invokingState) + self.parser = parser + + + def getRuleIndex(self): + return TreeParser.RULE_int_tree + + + def copyFrom(self, ctx:ParserRuleContext): + super().copyFrom(ctx) + + + + class NodeContext(Int_treeContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a TreeParser.Int_treeContext + super().__init__(parser) + self.copyFrom(ctx) + + def INT(self): + return self.getToken(TreeParser.INT, 0) + def int_tree(self, i:int=None): + if i is None: + return self.getTypedRuleContexts(TreeParser.Int_treeContext) + else: + return self.getTypedRuleContext(TreeParser.Int_treeContext,i) + + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterNode" ): + listener.enterNode(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitNode" ): + listener.exitNode(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitNode" ): + return visitor.visitNode(self) + else: + return visitor.visitChildren(self) + + + class LeafContext(Int_treeContext): + + def __init__(self, parser, ctx:ParserRuleContext): # actually a TreeParser.Int_treeContext + super().__init__(parser) + self.copyFrom(ctx) + + def INT(self): + return self.getToken(TreeParser.INT, 0) + + def enterRule(self, listener:ParseTreeListener): + if hasattr( listener, "enterLeaf" ): + listener.enterLeaf(self) + + def exitRule(self, listener:ParseTreeListener): + if hasattr( listener, "exitLeaf" ): + listener.exitLeaf(self) + + def accept(self, visitor:ParseTreeVisitor): + if hasattr( visitor, "visitLeaf" ): + return visitor.visitLeaf(self) + else: + return visitor.visitChildren(self) + + + + def int_tree(self): + + localctx = TreeParser.Int_treeContext(self, self._ctx, self.state) + self.enterRule(localctx, 2, self.RULE_int_tree) + self._la = 0 # Token type + try: + self.state = 17 + self._errHandler.sync(self) + token = self._input.LA(1) + if token in [TreeParser.INT]: + localctx = TreeParser.LeafContext(self, localctx) + self.enterOuterAlt(localctx, 1) + self.state = 7 + self.match(TreeParser.INT) + pass + elif token in [TreeParser.T__0]: + localctx = TreeParser.NodeContext(self, localctx) + self.enterOuterAlt(localctx, 2) + self.state = 8 + self.match(TreeParser.T__0) + self.state = 9 + self.match(TreeParser.INT) + self.state = 11 + self._errHandler.sync(self) + _la = self._input.LA(1) + while True: + self.state = 10 + self.int_tree() + self.state = 13 + self._errHandler.sync(self) + _la = self._input.LA(1) + if not (_la==TreeParser.T__0 or _la==TreeParser.INT): + break + + self.state = 15 + self.match(TreeParser.T__1) + pass + else: + raise NoViableAltException(self) + + except RecognitionException as re: + localctx.exception = re + self._errHandler.reportError(self, re) + self._errHandler.recover(self, re) + finally: + self.exitRule() + return localctx + + + + + diff --git a/TP03/tree/TreeVisitor.py b/TP03/tree/TreeVisitor.py new file mode 100644 index 0000000..e2a63ba --- /dev/null +++ b/TP03/tree/TreeVisitor.py @@ -0,0 +1,28 @@ +# Generated from Tree.g4 by ANTLR 4.9.2 +from antlr4 import * +if __name__ is not None and "." in __name__: + from .TreeParser import TreeParser +else: + from TreeParser import TreeParser + +# This class defines a complete generic visitor for a parse tree produced by TreeParser. + +class TreeVisitor(ParseTreeVisitor): + + # Visit a parse tree produced by TreeParser#top. + def visitTop(self, ctx:TreeParser.TopContext): + return self.visitChildren(ctx) + + + # Visit a parse tree produced by TreeParser#leaf. + def visitLeaf(self, ctx:TreeParser.LeafContext): + return self.visitChildren(ctx) + + + # Visit a parse tree produced by TreeParser#node. + def visitNode(self, ctx:TreeParser.NodeContext): + return self.visitChildren(ctx) + + + +del TreeParser \ No newline at end of file diff --git a/TP03/tree/main.py b/TP03/tree/main.py new file mode 100644 index 0000000..3e3c8d6 --- /dev/null +++ b/TP03/tree/main.py @@ -0,0 +1,35 @@ +from TreeLexer import TreeLexer +from TreeParser import TreeParser +from TreeVisitor import TreeVisitor + +from antlr4 import InputStream, CommonTokenStream +import sys + +class MyTreeVisitor(TreeVisitor): + def visitLeaf(self, ctx): + return True + + def visitNode(self, ctx): + nodes = ctx.int_tree(); + if(len(nodes)>2): + return False + for node in nodes: + if(not self.visit(node)): + return False + return True + + def visitTop(self, ctx): + return self.visit(ctx.int_tree()) + +def main(): + lexer = TreeLexer(InputStream(sys.stdin.read())) + stream = CommonTokenStream(lexer) + parser = TreeParser(stream) + tree = parser.int_tree_top() + visitor = MyTreeVisitor() + b = visitor.visit(tree) + print("Is it a binary tree ? " + str(b)) + + +if __name__ == '__main__': + main()