diff --git a/src/Visitors.py b/src/Visitors.py index 0c7dd42d..9de9207e 100644 --- a/src/Visitors.py +++ b/src/Visitors.py @@ -80,11 +80,13 @@ def searchScope(self, identifier: str): return scope.keys().__contains__(identifier) def searchIdentifier(self, identifier: str): + index = len(self.Stack) - 1 for scope in reversed(self.Stack): if (len(scope) != 0): if(scope.keys().__contains__(identifier)): - return self.Stack.index(scope) - return -1 + return index + index -= 1 + return index def searchType(self, identifier: str): for scope in reversed(self.Stack): @@ -603,7 +605,7 @@ def visitIf(self, ctx:COOL.IfContext): # Visit a parse tree produced by COOL#while. def visitWhile(self, ctx: COOL.WhileContext): - whileValue = ctx.getChild(3).accept(self) + ctx.getChild(3).accept(self) #chequea semanticamente el cuerpo whileValue = ctx.getChild(1).accept(self) if whileValue == "None" or whileValue == "Bool": return "Object" @@ -848,6 +850,7 @@ def visitProgram(self, ctx: COOL.ProgramContext, fileName: str): self.ConstantTable.append(("", "String", "str_const0")) self.ConstantTable.append((0, "Int", "int_const0")) self.ConstantTable.append(("false", "Bool", "bool_const0")) + self.ConstantTable.append(("true", "Bool", "bool_const1")) self.ConstantTable.append((fileName, "String", "str_const1")) self.ConstantTable.append((len(fileName), "Int", F"int_const{len(fileName)}")) self.Counter = 2 @@ -905,7 +908,6 @@ def visitProperty(self, ctx: COOL.PropertyContext): # Visit a parse tree produced by COOL#formal. def visitFormal(self, ctx: COOL.FormalContext): parent = ctx.parentCtx - className = parent.parentCtx.getChild(1).symbol.text methodName = parent.getChild(0).symbol.text method = self.TypeTable[className].Methods[methodName] @@ -1057,6 +1059,23 @@ class CodegenVisitor(ParseTreeVisitor): CurrentType: str + def join(self, class1: str, class2: str): + if class1 == "None" or class2 == "None": + return "None" + if class1 == "SELF_TYPE": + class1 = self.CurrentClass.Name + if class2 == "SELF_TYPE": + class2 = self.CurrentClass.Name + if self.TypeTable[class1].Deep == self.TypeTable[class2].Deep: + if self.TypeTable[class1].Name == self.TypeTable[class2].Name: + return class1 + else: + return self.join(self.TypeTable[class1].Parent, self.TypeTable[class2].Parent) + elif self.TypeTable[class1].Deep > self.TypeTable[class2].Deep: + return self.join(self.TypeTable[class1].Parent, class2) + else: + return self.join(class1, self.TypeTable[class2].Parent) + def searchAtributeInfo(self, coolClass: str, atributeName: str): for atribute in self.TypeTable[coolClass].Atributes.keys(): if atribute == atributeName: @@ -1091,14 +1110,14 @@ def genConstant(self, sol: str): sol = sol + \ f"\t.word -1\n" \ f"{constLabel}:\n" \ - f"\t.word 5\n" \ + f"\t.word 3\n" \ f"\t.word 4\n" \ f"\t.word Bool_dispTab\n" \ f"\t.word {constLabel[-1]}\n" elif constType == "Int": sol = sol + \ f"\t.word -1\n{constLabel}:\n" \ - f"\t.word 3\n\t.word 4\n" \ + f"\t.word 2\n\t.word 4\n" \ f"\t.word Int_dispTab\n" \ f"\t.word {constName}\n" else: @@ -1107,7 +1126,7 @@ def genConstant(self, sol: str): length = length + 1 sol = sol + \ f"\t.word -1\n{constLabel}:\n" \ - f"\t.word 4\n\t.word {length}\n" \ + f"\t.word 1\n\t.word {length}\n" \ f"\t.word String_dispTab\n" \ f"\t.word int_const{len(constName)}\n" \ f"\t.ascii \"{constName}\"\n" \ @@ -1125,20 +1144,23 @@ def genMethodNames(self, coolClass: str, coolMethods: list, className: str): if coolClass == "None": return "" temp = "" - methodList = list() for method in self.TypeTable[coolClass].Methods: if not (coolMethods.__contains__(method)): temp = temp + f"\t.word {coolClass}.{method}\n" - methodList.append(method) coolMethods.append(method) code = self.genMethodNames(self.TypeTable[coolClass].Parent, coolMethods, className) - if coolClass != "Object": - self.TypeTable[coolClass].TagMethods = self.TypeTable[self.TypeTable[coolClass].Parent].TagMethods + methodList - else: - self.TypeTable[coolClass].TagMethods = methodList return code + temp + def genMethodTags(self, coolClass: str, coolMethods: list, className: str): + if coolClass == "None": + return coolMethods + coolMethods = self.genMethodTags(self.TypeTable[coolClass].Parent, coolMethods, className) + for method in self.TypeTable[coolClass].Methods: + if not (coolMethods.__contains__(method)): + coolMethods.append(method) + return coolMethods + def genAtributeNames(self, coolClass: str, coolAtributes: list): if coolClass == "None": return "" @@ -1149,7 +1171,7 @@ def genAtributeNames(self, coolClass: str, coolAtributes: list): listAtributes.append(atribute) value = self.TypeTable[coolClass].Atributes[atribute] if value == "Int" or value == "String" or value == "Bool": - temp = temp + f"\t.word {value.lower()}_constant0\n" + temp = temp + f"\t.word {value.lower()}_const0\n" else: temp = temp + f"\t.word 0\n" coolAtributes.append(atribute) @@ -1187,7 +1209,7 @@ def genClassTable(self): f"\t.word {counter}\n" \ f"\t.word 5\n" \ f"\t.word {className}_dispTab\n" \ - f"\t.word int_constant0\n" \ + f"\t.word int_const0\n" \ f"\t.word 0\n" else: atributeList = list() @@ -1217,7 +1239,6 @@ def genClassAtributes(self, className: str): def visitProgram(self, ctx: COOL.ProgramContext, outFilename: str): for className in self.TypeTable: constantName = className - self.ConstantTable.append((constantName, "String", f"str_const{self.Counter}")) self.Counter = self.Counter + 1 length = len(constantName) @@ -1228,6 +1249,7 @@ def visitProgram(self, ctx: COOL.ProgramContext, outFilename: str): contain = False if contain: self.ConstantTable.append((length, "Int", f"int_const{length}")) + self.TypeTable[className].TagMethods = self.genMethodTags(className,list(),className) self.ConstantTable.append(("SELF_TYPE", "String", f"str_const{self.Counter}")) contain = True length = len("SELF_TYPE") @@ -1253,6 +1275,7 @@ def visitProgram(self, ctx: COOL.ProgramContext, outFilename: str): for className in self.TypeTable: self.CurrentClass = self.TypeTable[className] self.CurrentType = className + self.CurrentMethod = "None" code = code + f"{className}_init:\n" temp = self.genClassAtributes(className) if len(temp) != 0: @@ -1293,12 +1316,12 @@ def visitProgram(self, ctx: COOL.ProgramContext, outFilename: str): "\taddiu $fp $sp 4\n" \ "\tmove $s0 $a0\n" code = code + (self.TypeTable[className].Methods[methodName].InstructionSet.accept(self) or "") + # "\tmove $a0 $s0\n" \ code = code + \ - "\tmove $a0 $s0\n" \ "\tlw $fp 12($sp)\n" \ "\tlw $s0 8($sp)\n" \ "\tlw $ra 4($sp)\n" \ - "\taddiu $sp $sp 12\n" + f"\taddiu $sp $sp {12+4*self.CurrentClass.Methods[methodName].ParamsNumber}\n" code = code + "\tjr $ra\n" self.ScopeManager.deleteScope() @@ -1342,7 +1365,31 @@ def visitFormal(self, ctx: COOL.FormalContext): # Visit a parse tree produced by COOL#letIn. def visitLetIn(self, ctx: COOL.LetInContext): - return self.visitChildren(ctx) + self.ScopeManager.addScope() + count = 0 + varNumber = 0 + code = "" + while (ctx.getChild(count).symbol.text != "in"): + idName = ctx.getChild(count + 1).symbol.text + varNumber += 1 + count = count + 2 + idType = ctx.getChild(count + 1).symbol.text + count = count + 2 + if ctx.getChild(count).symbol.text == "<-": + code += ctx.getChild(count + 1).accept(self) + count = count + 2 + else: + if idType == "String" or idType == "Int" or idType == "Bool": + code += f"\tla $a0 {idType.lower()}_const0\n" + else: + code += "li $a0 0\n" + code += f"\tsw $a0 0($sp)\n" \ + f"\taddiu $sp $sp -4\n" + self.ScopeManager.addIdentifier(idName, idType) + code += ctx.getChild(count + 1).accept(self) + code += f"\taddiu $sp $sp {varNumber * 4}\n" + self.ScopeManager.deleteScope() + return code # Visit a parse tree produced by COOL#minus. def visitMinus(self, ctx: COOL.MinusContext): @@ -1372,17 +1419,35 @@ def visitString(self, ctx: COOL.StringContext): # Visit a parse tree produced by COOL#isvoid. def visitIsvoid(self, ctx: COOL.IsvoidContext): - return self.visitChildren(ctx) + code = ctx.getChild(1).accept(self) + code += \ + "\tla $t1 bool_const0\n" \ + "\tla $t2 bool_const1\n" \ + "\tmovz $t1 $t2 $a0\n" \ + "\tmove $a0 $t1\n" + self.CurrentType = "Bool" + return code # Visit a parse tree produced by COOL#while. def visitWhile(self, ctx: COOL.WhileContext): - return self.visitChildren(ctx) + code = f"while_label{self.Counter}:\n" + code += ctx.getChild(1).accept(self) + code += "\tlw $t1 12($a0)\n" + \ + f"\tbgtz $t1 loop_label{self.Counter}\n" + \ + f"\tb pool_label{self.Counter}\n" + \ + f"loop_label{self.Counter}:\n" + code += ctx.getChild(3).accept(self) + code += f"\tb while_label{self.Counter}\n" + \ + f"pool_label{self.Counter}:\n" + self.CurrentType = "None" + self.Counter += 1 + return code # Visit a parse tree produced by COOL#division. def visitDivision(self, ctx: COOL.DivisionContext): code = ctx.getChild(0).accept(self) code += \ - "\tsw $a0 0 ($sp)\n" + \ + "\tsw $a0 0($sp)\n" + \ "\taddiu $sp $sp -4\n" code += ctx.getChild(2).accept(self) code += \ @@ -1398,15 +1463,48 @@ def visitDivision(self, ctx: COOL.DivisionContext): # Visit a parse tree produced by COOL#negative. def visitNegative(self, ctx: COOL.NegativeContext): - return self.visitChildren(ctx) + self.CurrentType = "Int" + code = ctx.getChild(1).accept(self) + code += \ + "\tjal Object.copy\n" \ + "\tlw $t1 12($a0)\n" \ + "\tnegu $t1 $t1\n" \ + "\tsw $t1 12($a0)\n" \ + "\tsw $a0 0($sp)\n" + return code # Visit a parse tree produced by COOL#boolNot. def visitBoolNot(self, ctx: COOL.BoolNotContext): - return self.visitChildren(ctx) + self.CurrentType = "Bool" + code = ctx.getChild(1).accept(self) + code += \ + "\tjal Object.copy\n" \ + "\tlw $t1 12($a0)\n" \ + "\tnegu $t2 $t1\n" \ + "\taddiu $t3 $t2 1\n"\ + "\tsw $t3 12($a0)\n" \ + "\tsw $a0 0($sp)\n" + return code # Visit a parse tree produced by COOL#lessThan. def visitLessThan(self, ctx: COOL.LessThanContext): - return self.visitChildren(ctx) + self.CurrentType = "Bool" + code = ctx.getChild(0).accept(self) + code += \ + "\tsw $a0 0($sp)\n" + \ + "\taddiu $sp $sp -4\n" + code += ctx.getChild(2).accept(self) + code += \ + "\tjal Object.copy\n" \ + "\tlw $t0 4($sp)\n" \ + "\tlw $t1 12($t0)\n" \ + "\tlw $t2 12($a0)\n" \ + "\tslt $t3 $t1 $t2\n" \ + "\tla $a0 bool_const0\n" \ + "\tjal Object.copy\n" \ + "\tsw $t3 12($a0)\n" \ + "\taddiu $sp $sp 4\n" + return code # Visit a parse tree produced by COOL#block. def visitBlock(self, ctx: COOL.BlockContext): @@ -1426,9 +1524,9 @@ def visitId(self, ctx: COOL.IdContext): return "\tlw $a0 ($s0)\n" self.CurrentType = self.ScopeManager.searchType(varName) option = self.ScopeManager.searchIdentifier(varName) - if option == 0: + if option == 0 and self.CurrentMethod != "None": return self.propertyId(ctx) - elif option == 1: + elif option == 1 and self.CurrentMethod != "None": return self.formalId(ctx) else: return self.variableId(ctx) @@ -1444,17 +1542,19 @@ def formalId(self, ctx: COOL.AssignmentContext): varType = self.ScopeManager.Stack[1][varName] pos = self.CurrentMethod.Params.index((varName,varType)) total = self.CurrentMethod.ParamsNumber - code = f"\tlw $a0 {(pos - (total + 2)) * 4}($fp)\n" + code = f"\tlw $a0 {((total + 2) - pos) * 4}($fp)\n" return code def variableId(self, ctx: COOL.AssignmentContext): varName = ctx.getChild(0).symbol.text scope = self.ScopeManager.searchIdentifier(varName) - pos = list(self.ScopeManager.Stack[scope].keys()).index(varName) - total = 0 - for scope in self.ScopeManager.Stack [2 : pos]: - total += len(list(scope.keys())) - code = f"\tlw $a0 {(total + pos) * 4}($fp)\n" + pos = list(self.ScopeManager.Stack[scope].keys()).index(varName) + 1 + init = 2 + if self.CurrentMethod == "None": + init = 0 + for scope in list(self.ScopeManager.Stack)[init : scope]: + pos += len(list(scope.keys())) + code = f"\tlw $a0 {-(pos * 4)}($fp)\n" return code # Visit a parse tree produced by COOL#multiply. @@ -1476,11 +1576,67 @@ def visitMultiply(self, ctx: COOL.MultiplyContext): # Visit a parse tree produced by COOL#if. def visitIf(self, ctx: COOL.IfContext): - return self.visitChildren(ctx) + code = ctx.getChild(1).accept(self) + counter = self.Counter + self.Counter += 1 + code = code + \ + "\tlw $t1 12($a0)\n" + \ + f"\tbgtz $t1 then_label{counter}\n" + \ + f"\tb else_label{counter}\n" + \ + f"then_label{counter}:\n" + code = code +\ + ctx.getChild(3).accept(self) + \ + f"\tb fi_label{counter}\n" + \ + f"else_label{counter}:\n" + tempType = self.CurrentType + code = code +\ + ctx.getChild(5).accept(self) + \ + f"\tb fi_label{counter}\n" + \ + f"fi_label{counter}:\n" + self.CurrentType = self.join(tempType, self.CurrentType) + return code # Visit a parse tree produced by COOL#case. def visitCase(self, ctx: COOL.CaseContext): - return "" + counter = self.Counter + self.Counter += 1 + code = ctx.getChild(1).accept(self) +\ + "\tli $t1 0\n" \ + f"\tbeq $a0 $t1 abort{counter}\n" + lengt = len(ctx.children) - 1 + tempCode = f"abort{counter}:\n" \ + "\tjal _case_abort2\n" + count = 3 + while lengt > count: + idName = ctx.getChild(count).symbol.text + count = count + 2 + idType = ctx.getChild(count).symbol.text + count = count + 2 + self.ScopeManager.addScope() + self.ScopeManager.addIdentifier(idName, idType) + code += \ + f"\tlw $t1 0($a0)\n" \ + f"\tli $t2 {self.TypeTable[idType].Tag}\n" \ + f"\tbeq $t1 $t2 {idType}_case{counter}\n" + scope = self.ScopeManager.searchIdentifier(idName) + pos = list(self.ScopeManager.Stack[scope].keys()).index(idName) + 1 + init = 2 + if self.CurrentMethod == "None": + init = 0 + for scope in list(self.ScopeManager.Stack)[init: scope]: + pos += len(list(scope.keys())) + tempCode +=\ + f"{idType}_case{counter}:\n" \ + f"\tsw $a0 -{pos * 4}($fp)\n" + tempCode += ctx.getChild(count).accept(self) + tempCode += f"\tb esac{counter}\n" + self.ScopeManager.deleteScope() + count = count + 2 + code = code + \ + "\tjal _case_abort\n" + code += tempCode +\ + f"esac{counter}:\n" + return code # Visit a parse tree produced by COOL#ownMethodCall. def visitOwnMethodCall(self, ctx: COOL.OwnMethodCallContext): @@ -1522,19 +1678,21 @@ def visitAdd(self, ctx: COOL.AddContext): # Visit a parse tree produced by COOL#new. def visitNew(self, ctx: COOL.NewContext): self.CurrentType = ctx.getChild(1).symbol.text - return self.visitChildren(ctx) + return f"\tla $a0 {self.CurrentType}_protObj\n"\ + "\tjal Object.copy\n" \ + f"\tjal {self.CurrentType}_init\n" # Visit a parse tree produced by COOL#parentheses. def visitParentheses(self, ctx: COOL.ParenthesesContext): - return self.visitChildren(ctx) + return ctx.getChild(1).accept(self) # Visit a parse tree produced by COOL#assignment. def visitAssignment(self, ctx: COOL.AssignmentContext): varName = ctx.getChild(0).symbol.text option = self.ScopeManager.searchIdentifier(varName) - if option == 0: + if option == 0 and self.CurrentMethod != "None": return self.propertyAssignament(ctx) - elif option == 1: + elif option == 1 and self.CurrentMethod != "None": return self.formalAssignament(ctx) else: return self.variableAssignament(ctx) @@ -1558,17 +1716,20 @@ def formalAssignament(self, ctx: COOL.AssignmentContext): def variableAssignament(self, ctx: COOL.AssignmentContext): varName = ctx.getChild(0).symbol.text scope = self.ScopeManager.searchIdentifier(varName) - pos = list(self.ScopeManager.Stack[scope].keys()).index(varName) - total = 0 - for scope in self.ScopeManager.Stack[2: pos]: - total += len(list(scope.keys())) - code = f"\tsw $a0 {(total + pos) * 4}($fp)\n" + pos = list(self.ScopeManager.Stack[scope].keys()).index(varName) + 1 + init = 2 + if self.CurrentMethod == "None": + init = 0 + for scope in list(self.ScopeManager.Stack)[init: scope]: + pos += len(list(scope.keys())) + code = ctx.getChild(2).accept(self) + code += f"\tsw $a0 -{pos * 4}($fp)\n" return code # Visit a parse tree produced by COOL#false. def visitFalse(self, ctx: COOL.FalseContext): self.CurrentType = "Bool" - return f"\tla $a0 {bool_const0}\n" + return "\tla $a0 bool_const0\n" # Visit a parse tree produced by COOL#int. def visitInt(self, ctx: COOL.IntContext): @@ -1581,41 +1742,75 @@ def visitInt(self, ctx: COOL.IntContext): # Visit a parse tree produced by COOL#equal. def visitEqual(self, ctx: COOL.EqualContext): - return self.visitChildren(ctx) + code = ctx.getChild(0).accept(self) + code += \ + "\tsw $a0 0($sp)\n" + \ + "\taddiu $sp $sp -4\n" + code += ctx.getChild(2).accept(self) + code += \ + "\tmove $t2 $a0\n" \ + "\tlw $t1 4($sp)\n" \ + "\taddiu $sp $sp 4\n" \ + "\tla $a0 bool_const1\n" \ + "\tla $a1 bool_const0\n" \ + "\tjal equality_test\n" + self.CurrentType = "Bool" + return code # Visit a parse tree produced by COOL#true. def visitTrue(self, ctx: COOL.TrueContext): self.CurrentType = "Bool" - return f"\tla $a0 bool_const1\n" + return "\tla $a0 bool_const1\n" # Visit a parse tree produced by COOL#lessEqual. def visitLessEqual(self, ctx: COOL.LessEqualContext): - return self.visitChildren(ctx) + code = ctx.getChild(0).accept(self) + code += \ + "\tsw $a0 0($sp)\n" + \ + "\taddiu $sp $sp -4\n" + code += ctx.getChild(2).accept(self) + code += \ + "\tjal Object.copy\n" \ + "\tlw $t0 4($sp)\n" \ + "\tlw $t1 12($t0)\n" \ + "\tlw $t2 12($a0)\n" \ + "\tslt $t3 $t2 $t1\n" \ + "\tnegu $t4 $t3\n" \ + "\taddiu $t5 $t4 1\n" \ + "\tla $a0 bool_const0\n" \ + "\tjal Object.copy\n" \ + "\tsw $t5 12($a0)\n" \ + "\taddiu $sp $sp 4\n" + self.CurrentType = "Bool" + return code # Visit a parse tree produced by COOL#methodCall. def visitMethodCall(self, ctx: COOL.MethodCallContext): length = 5 - code = ctx.getChild(0).accept(self) or "" + methodPos = 2 + objCode = ctx.getChild(0).accept(self) + code = "" classId = self.CurrentType if ctx.getChild(1).symbol.text == "@": length += 2 + methodPos += 2 classId = ctx.getChild(2).symbol.text + count = methodPos + 2 if len(ctx.children) > length: - count = length - 1 + length = len(ctx.children) while length != count: param = (ctx.getChild(count).accept(self) or "") code += param + \ f"\tsw $a0 0($sp)\n" \ f"\taddiu $sp $sp -4\n" count = count + 2 - methodIdx = self.TypeTable[classId].TagMethods.index(ctx.getChild(length - 3).symbol.text) - self.CurrentType = self.searchMethodInfo(self.CurrentClass.Name, ctx.getChild(length - 3).symbol.text) - code += "\tmove $a0 $s0\n" \ - "\tlw $t1 8($a0)\n" \ - f"\tlw $t1 {methodIdx * 4}($t1)\n" \ - "\tjalr $t1\n" + methodIdx = self.TypeTable[classId].TagMethods.index(ctx.getChild(methodPos).symbol.text) + self.CurrentType = self.searchMethodInfo(classId, ctx.getChild(methodPos).symbol.text) + code += objCode + \ + "\tlw $t1 8($a0)\n" \ + f"\tlw $t1 {methodIdx * 4}($t1)\n" \ + "\tjalr $t1\n" return code - return "" RuntimeMessages = """ # diff --git a/tests/codegen/arith.cl b/tests/codegen/arith.cl index a1035961..9e7ce2c4 100755 --- a/tests/codegen/arith.cl +++ b/tests/codegen/arith.cl @@ -338,7 +338,13 @@ class Main inherits IO { main() : Object { { - avar <- (new A); + --avar <- (new A); + + avar <- (new C)@A.method5(avar.value()); + + -- print(avar); + +(* while flag loop { -- avar <- (new A).set_var(get_int()); @@ -423,7 +429,9 @@ class Main inherits IO { fi fi fi fi fi fi fi fi fi fi; } pool; +*) } + }; }; diff --git a/tests/codegen/atoi.cl b/tests/codegen/atoi.cl index fd8b2ea4..1ace1efb 100644 --- a/tests/codegen/atoi.cl +++ b/tests/codegen/atoi.cl @@ -13,9 +13,9 @@ something of type A2I, or simpl write (new A2I).method(argument). class A2I { c2i(char : String) : Int { - if char = "0" then 0 else - if char = "1" then 1 else - if char = "2" then 2 else + if char = "0" then 0 else + if char = "1" then 1 else + if char = "2" then 2 else if char = "3" then 3 else if char = "4" then 4 else if char = "5" then 5 else @@ -54,9 +54,13 @@ overflow. *) a2i(s : String) : Int { - if s.length() = 0 then 0 else - if s.substr(0,1) = "-" then ~a2i_aux(s.substr(1,s.length()-1)) else - if s.substr(0,1) = "+" then a2i_aux(s.substr(1,s.length()-1)) else + if s.length() = 0 then + 0 + else if s.substr(0,1) = "-" then + ~a2i_aux(s.substr(1,s.length()-1)) + else if s.substr(0,1) = "+" then + a2i_aux(s.substr(1,s.length()-1)) + else a2i_aux(s) fi fi fi }; @@ -66,21 +70,17 @@ overflow. example, this method is written iteratively. *) a2i_aux(s : String) : Int { - (let int : Int <- 0 in - { - (let j : Int <- s.length() in - (let i : Int <- 0 in - while i < j loop - { - int <- int * 10 + c2i(s.substr(i,1)); - i <- i + 1; - } - pool - ) - ); - int; - } - ) + (let int : Int <- 0 in { + (let j : Int <- s.length() in + (let i : Int <- 0 in + while i < j loop { + int <- int * 10 + c2i(s.substr(i,1)); + i <- i + 1; + } pool + ) + ); + int; + }) }; (* @@ -108,14 +108,35 @@ numbers are handled correctly. }; class Main inherits IO { - main () : Object { - let a : Int <- (new A2I).a2i("678987"), - b : String <- (new A2I).i2a(678987) in + + c2i(char : String) : Int { + if char = "0" then 0 else + if char = "1" then 1 else + if char = "2" then 2 else + if char = "3" then 3 else + if char = "4" then 4 else + if char = "5" then 5 else + if char = "6" then 6 else + if char = "7" then 7 else + if char = "8" then 8 else + if char = "9" then 9 else + { abort(); 0; } -- the 0 is needed to satisfy the typchecker + fi fi fi fi fi fi fi fi fi fi + }; + + counter : Int <- 0; + + main () : Object { { + + let a : Int <- (new A2I).a2i("678987"), + b : String <- (new A2I).i2a(678987) in { out_int(a) ; out_string(" == ") ; out_string(b) ; - out_string("\n"); - } + out_string("\n"); + }; + + } } ; } ; diff --git a/tests/codegen/hello_world.cl b/tests/codegen/hello_world.cl index 7cefd7a3..ce2679b0 100755 --- a/tests/codegen/hello_world.cl +++ b/tests/codegen/hello_world.cl @@ -1,6 +1,7 @@ class Main inherits IO { - x : Int <- 1; + x : Int <- let x : Int <- 5, y : Int <- 4 in (x + y); + y : Bool <- true; sqrt (x : Int) : Int { x * x @@ -8,13 +9,14 @@ class Main inherits IO { main(): IO { { - out_string("Hello, World ("); - out_int(x * 2); - x <- 0 -7; - x <- sqrt(x); - out_string(", "); + (*while x < 10 loop{ out_int(x); - out_string(").\n"); + out_string("\n"); + x <- x + 1; + } pool;*) + case x of y : Int => y <- 10 ;esac; + out_int(x); + } }; };