diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..5dba2172 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..c6f94a91 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "python.linting.pylintEnabled": true, + "python.linting.prospectorEnabled": false, + "python.linting.enabled": true +} \ No newline at end of file diff --git a/src/INFORME DEL PROYECTO DE COMPILACION.pdf b/src/INFORME DEL PROYECTO DE COMPILACION.pdf new file mode 100644 index 00000000..d67480c3 Binary files /dev/null and b/src/INFORME DEL PROYECTO DE COMPILACION.pdf differ diff --git a/src/ast_hierarchy.py b/src/ast_hierarchy.py new file mode 100644 index 00000000..932e96c1 --- /dev/null +++ b/src/ast_hierarchy.py @@ -0,0 +1,166 @@ +class Node: + def __init__(self, line_number): + self.lineNumber = line_number + + def getLineNumber(self): + return 0 if len(self.lineNumber) != 1 else self.lineNumber[0][0] + + def getColumnNumber(self): + return 0 if len(self.lineNumber) != 1 else self.lineNumber[0][1] + +class ProgramNode(Node): + def __init__(self, classes, line_number): + super().__init__(line_number) + self.classes = classes + +class ClassNode(Node): + def __init__(self, type_name, features, father_type_name, line_number): + super().__init__(line_number) + self.typeName = type_name + self.features = features + self.fatherTypeName = father_type_name + +class FeatureNode(Node): + pass + +class AttributeFeatureNode(FeatureNode): + def __init__(self, attr_id, type_name, expression, line_number): + super().__init__(line_number) + self.id = attr_id + self.typeName = type_name + self.expression = expression + +class FunctionFeatureNode(FeatureNode): + def __init__(self, func_id, parameters, type_name, statement, line_number): + super().__init__(line_number) + self.id = func_id + self.parameters = parameters + self.typeName = type_name + self.statements = statement + +class ParameterNode(Node): + def __init__(self, param_id, type_name, line_number): + super().__init__(line_number) + self.id = param_id + self.typeName = type_name + +class StatementNode(Node): + pass + +class AssignStatementNode(StatementNode): + def __init__(self, assign_id, expression, line_number): + super().__init__(line_number) + self.id = assign_id + self.expression = expression + +class ConditionalStatementNode(StatementNode): + def __init__(self, eval_expr, if_expr, else_expr, line_number): + super().__init__(line_number) + self.evalExpr = eval_expr + self.ifExpr = if_expr + self.elseExpr = else_expr + +class LoopStatementNode(StatementNode): + def __init__(self, eval_expr, loop_expr, line_number): + super().__init__(line_number) + self.evalExpr = eval_expr + self.loopExpr = loop_expr + +class BlockStatementNode(StatementNode): + def __init__(self, expressions, line_number): + super().__init__(line_number) + self.expressions = expressions + +class LetStatementNode(StatementNode): + def __init__(self, variables, expression, line_number): + super().__init__(line_number) + self.variables = variables + self.expression = expression + +class CaseStatementNode(StatementNode): + def __init__(self, expression, body, line_number): + super().__init__(line_number) + self.expression = expression + self.body = body + +class CaseBranchNode(StatementNode): + def __init__(self, case_id, type_name, expression, line_number): + super().__init__(line_number) + self.id = case_id + self.typeName = type_name + self.expression = expression + +class NewStatementNode(StatementNode): + def __init__(self, type_name, line_number): + super().__init__(line_number) + self.typeName = type_name + +class FunctionCallStatement(StatementNode): + def __init__(self, instance, dispatch_type, function, args, line_number): + super().__init__(line_number) + self.instance = instance + self.dispatchType = dispatch_type + self.function = function + self.args = args + self.instance_type = "" + +class ExpressionNode(Node): + pass + +class AtomicNode(ExpressionNode): + def __init__(self, lex, line_number): + super().__init__(line_number) + self.lex = lex + +class UnaryNode(ExpressionNode): + def __init__(self, expression, line_number): + super().__init__(line_number) + self.expression = expression + +class BinaryNode(ExpressionNode): + def __init__(self, left, right, line_number): + super().__init__(line_number) + self.left = left + self.right = right + +class ConstantNumericNode(AtomicNode): + pass + +class ConstantStringNode(AtomicNode): + pass + +class ConstantBoolNode(AtomicNode): + pass + +class VariableNode(AtomicNode): + pass + +class NotNode(UnaryNode): + pass + +class IsVoidNode(UnaryNode): + pass + +class ComplementNode(UnaryNode): + pass + +class LessEqualNode(BinaryNode): + pass + +class LessNode(BinaryNode): + pass + +class EqualNode(BinaryNode): + pass + +class PlusNode(BinaryNode): + pass + +class MinusNode(BinaryNode): + pass + +class TimesNode(BinaryNode): + pass + +class DivideNode(BinaryNode): + pass \ No newline at end of file diff --git a/src/cil_hierarchy.py b/src/cil_hierarchy.py new file mode 100644 index 00000000..e795f440 --- /dev/null +++ b/src/cil_hierarchy.py @@ -0,0 +1,254 @@ + + +class CILNode: + pass + + +class CILProgramNode(CILNode): + def __init__(self, dottypes, dotdata, dotcode): + self.dottypes = dottypes + self.dotdata = dotdata + self.dotcode = dotcode + + +class CILTypeNode(CILNode): + def __init__(self, cinfo, attrs, methods): + self.cinfo = cinfo + self.attrs = attrs + self.methods = methods + +class CILSaveState(CILNode): + pass + +class CILDataNode(CILNode): + def __init__(self, vname, value): + self.vname = vname + self.value = value + + +class CILFunctionNode(CILNode): + def __init__(self, finfo, arguments, localvars, instructions): + self.finfo = finfo + self.arguments = arguments + self.localvars = localvars + self.instructions = instructions + + +class CILParamNode(CILNode): + def __init__(self, vinfo): + self.vinfo = vinfo + + +class CILLocalNode(CILNode): + def __init__(self, vinfo): + self.vinfo = vinfo + + +class CILInstructionNode(CILNode): + pass + + +class CILAssignNode(CILInstructionNode): + def __init__(self, dest, source): + self.dest = dest + self.source = source + + +class CILArithmeticNode(CILInstructionNode): + def __init__(self, dest, left, right): + self.dest = dest + self.left = left + self.right = right + + +class CILPlusNode(CILArithmeticNode): + pass + + +class CILMinusNode(CILArithmeticNode): + pass + + +class CILStarNode(CILArithmeticNode): + pass + + +class CILDivNode(CILArithmeticNode): + pass + + +class CILGetAttribNode(CILInstructionNode): + def __init__(self, dest, source, nattr): + self.dest = dest + self.source = source + self.nattr = nattr + + +class CILSetAttribNode(CILInstructionNode): + def __init__(self, dest, nattr, source): + self.dest = dest + self.nattr = nattr + self.source = source + + +class CILGetIndexNode(CILInstructionNode): + def __init__(self, dest, array, index): + self.dest = dest + self.array = array + self.index = index + + +class CILSetIndexNode(CILInstructionNode): + def __init__(self, array, index, source): + self.array = array + self.index = index + self.source = source + + +class CILAllocateNode(CILInstructionNode): + def __init__(self, dest, cinfo): + self.dest = dest + self.cinfo = cinfo + + +class CILArrayNode(CILInstructionNode): + def __init__(self, dest, size): + self.dest = dest + self.size = size + + +class CILTypeOfNode(CILInstructionNode): + def __init__(self, dest, var): + self.dest = dest + self.var = var + + +class CILLabelNode(CILInstructionNode): + def __init__(self, name): + self.name = name + + +class CILGotoNode(CILInstructionNode): + def __init__(self, label): + self.label = label + + +class CILGotoIfNode(CILInstructionNode): + def __init__(self, vinfo, label): + self.vinfo = vinfo + self.label = label + + +class CILStaticCallNode(CILInstructionNode): + def __init__(self, dest, meth_name): + self.dest = dest + self.meth_name = meth_name + + +class CILDynamicCallNode(CILInstructionNode): + def __init__(self, dest, ctype, meth_name): + self.dest = dest + self.ctype = ctype + self.meth_name = meth_name + + +class CILArgNode(CILInstructionNode): + def __init__(self, vinfo): + self.vinfo = vinfo + + +class CILReturnNode(CILInstructionNode): + def __init__(self, value=None): + self.value = value + + +class CILLoadNode(CILInstructionNode): + def __init__(self, dest, msg): + self.dest = dest + self.msg = msg + + +class CILLengthNode(CILInstructionNode): + def __init__(self, dest, array): + self.dest = dest + self.array = array + + +class CILConcatNode(CILInstructionNode): + def __init__(self, dest, array1, array2): + self.dest = dest + self.array1 = array1 + self.array2 = array2 + + +class CILPrefixNode(CILInstructionNode): + def __init__(self, dest, array, n): + self.dest = dest + self.array = array + self.n = n + + +class CILSubstringNode(CILInstructionNode): + def __init__(self, dest, array, i, l): + self.dest = dest + self.array = array + self.i = i + self.l = l + + +class CILToStrNode(CILInstructionNode): + def __init__(self, dest, ivalue): + self.dest = dest + self.ivalue = ivalue + + +class CILReadNode(CILInstructionNode): + def __init__(self, vinfo): + self.vinfo = vinfo + + +class CILReadIntNode(CILReadNode): + pass + + +class CILReadStrNode(CILReadNode): + pass + + +class CILPrintNode(CILInstructionNode): + def __init__(self, vinfo): + self.vinfo = vinfo + + +class CILPrintIntNode(CILPrintNode): + pass + + +class CILPrintStrNode(CILPrintNode): + pass + + +class CILParentNode(CILInstructionNode): + def __init__(self, dest, ntype): + self.dest = dest + self.ntype = ntype + + +class CILErrorNode(CILInstructionNode): + def __init__(self, num = 1): + self.num = num + + +class CILLessThan(CILInstructionNode): + def __init__(self, dest, left, right): + self.dest = dest + self.left = left + self.right = right + +class CILTypeName(CILInstructionNode): + def __init__(self, dest, nclass): + self.dest = dest + self.nclass = nclass + +class CILReturnFinal(CILInstructionNode): + pass \ No newline at end of file diff --git a/src/cil_types.py b/src/cil_types.py new file mode 100644 index 00000000..8930cef1 --- /dev/null +++ b/src/cil_types.py @@ -0,0 +1,421 @@ +import ast_hierarchy as ast +import cil_hierarchy as cil +import visitor +from context import VariableInfo, MethodInfo, ClassInfo +from copy import copy + + +class CILTypes: + def __init__(self, type_hierachy): + self.type_hierachy = type_hierachy + + # La sección .TYPES del CIL + self.dottypes = {} + + self.dotdata = { + "exception_1": cil.CILDataNode("exception_1", "Se esta realizando dispatch sobre valor void"), + "exception_2": cil.CILDataNode("exception_2", "Se esta realizando case sobre valor void"), + "exception_3": cil.CILDataNode("exception_3", "El tipo de la expresion case no concuerda con ninguna rama"), + "exception_4": cil.CILDataNode("exception_4", "Division por cero"), + "exception_5": cil.CILDataNode("exception_5", "Substring fuera de rango"), + "exception_6": cil.CILDataNode("exception_6", "Abort"), + } + + self.dotcode = [] + + self.current_class_name = '' + + self.current_function_name = '' + + # Variables locales del método actual + self.localvars = [] + + # Instrucciones del método actual + self.instructions = [] + + # Parametros del metodo actual + self.arguments = [] + + self.internal_count = 0 + + self.void = 0 + + # Util Methods + def change_current_function(self, fname=''): + self.current_function_name = fname + self.localvars = [] + self.instructions = [] + self.arguments = [] + + def define_internal_local(self): + vinfo = VariableInfo('internal') + vinfo.name = self.build_internal_vname(vinfo.name) + return self.register_local(vinfo) + + def build_internal_vname(self, vname): + vname = '{}_{}'.format(vname, self.internal_count) + self.internal_count += 1 + return vname + + def build_funcname(self, fname): + fname = '{}_{}'.format(fname, self.internal_count) + self.internal_count += 1 + return fname + + def register_local(self, vinfo): + vinfo.vmholder = len(self.localvars) + len(self.arguments) + 1 + local_node = cil.CILLocalNode(vinfo) + self.localvars.append(local_node) + return local_node.vinfo + + def register_instruction(self, instruction): + self.instructions.append(instruction) + + def register_function(self, function): + self.dotcode.append(function) + + def build_label(self): + fname = 'label_type_{}'.format(self.internal_count) + self.internal_count += 1 + return cil.CILLabelNode(fname) + + def register_data(self, value): + vname = 'data_{}'.format(len(self.dotdata)) + data_node = cil.CILDataNode(vname, value) + self.dotdata[vname] = data_node + return data_node + + # Visit + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(ast.ProgramNode) + def visit(self, node: ast.ProgramNode): + object_class = self.object_bi() + self.dottypes['Object'] = object_class + self.dottypes['Int'] = self.int_bi(object_class) + self.dottypes['Bool'] = self.bool_bi(object_class) + self.dottypes['String'] = self.string_bi(object_class) + self.dottypes['IO'] = self.io_bi(object_class) + + for child in node.classes: + self.dottypes[child.typeName] = self.visit(child) + + self.change_current_function('entry') + vlocal = self.define_internal_local() + cclass = self.dottypes['Main'] + self.register_instruction(cil.CILAllocateNode(vlocal, cclass.cinfo)) + + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(vlocal)) + + vlocal2 = self.define_internal_local() + nctor = cclass.methods['ctor'].finfo.name + self.register_instruction(cil.CILStaticCallNode(vlocal2, nctor)) + + + mname = cclass.methods['main'].finfo.name + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(vlocal)) + self.register_instruction(cil.CILStaticCallNode(vlocal2, mname)) + self.register_instruction(cil.CILReturnFinal()) + + entry_m = cil.CILFunctionNode(MethodInfo(self.current_function_name), self.arguments, self.localvars, self.instructions) + self.register_function(entry_m) + + return cil.CILProgramNode(self.dottypes, self.dotdata, self.dotcode) + + @visitor.when(ast.ClassNode) + def visit(self, node: ast.ClassNode): + self.current_class_name = node.typeName + parent = self.dottypes[node.fatherTypeName.Name] + + attrs = copy(parent.attrs) + for feature in node.features: + if isinstance(feature, ast.AttributeFeatureNode): + # vinfo = feature.vinfo + vinfo = VariableInfo(feature.id, feature.typeName) + vinfo.vmholder = len(attrs.keys())+1 + attrs[feature.id] = vinfo + + ctor = self.build_funcname('ctor') + constructor = cil.CILFunctionNode(MethodInfo(ctor, vmholder=2), [], [], []) + self.register_function(constructor) + + methods = copy(parent.methods) + methods['ctor'] = constructor + + for feature in node.features: + if isinstance(feature, ast.FunctionFeatureNode): + meth_ = self.type_hierachy[self.current_class_name].MethList[feature.id] + finfo = MethodInfo(meth_.rename) + ffunc = cil.CILFunctionNode(finfo, [], [], []) + self.register_function(ffunc) + + if not methods.__contains__(feature.id): + ffunc.finfo.vmholder = len(methods.keys())+2 + else: + ffunc.finfo.vmholder = methods[feature.id].finfo.vmholder + + methods[feature.id] = ffunc + ffunc.finfo.paramsType = meth_.ParamsType + ffunc.finfo.returnType = meth_.ReturnType + + vinfo = ClassInfo(self.current_class_name, 4*len(attrs.keys()), 4*len(methods.keys()), parent) + return cil.CILTypeNode(vinfo, attrs, methods) + + # Tipos built-in + def object_bi(self): + attrs = {} + self.change_current_function() + self.arguments.append(cil.CILArgNode(VariableInfo('self', vmholder=1))) + # self.register_instruction(cil.CILSetAttribNode(self.arguments[0].vinfo, 'value', self.void)) + # self.register_instruction(cil.CILSetAttribNode(self.arguments[0].vinfo, 'type', self.void)) + self.register_instruction(cil.CILReturnNode()) + + ctor_func = cil.CILFunctionNode(MethodInfo(self.build_funcname('ctor'), vmholder= 2), self.arguments, self.localvars, self.instructions) + self.register_function(ctor_func) + + + self.change_current_function() + self.arguments.append(cil.CILArgNode(VariableInfo('self', vmholder=1))) + + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_6'])) + + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + self.register_instruction(cil.CILReturnNode()) + abort_func = cil.CILFunctionNode(MethodInfo(self.build_funcname('abort'), vmholder= 3, returnType='Object'), self.arguments, self.localvars, self.instructions) + self.register_function(abort_func) + + self.change_current_function() + self.arguments.append(cil.CILArgNode(VariableInfo('self', vmholder=1))) + vlocal = self.define_internal_local() + # self.register_instruction(cil.CILGetAttribNode(vlocal, self.arguments[0].vinfo, 'type')) + self.register_instruction(cil.CILTypeOfNode(vlocal, self.arguments[0].vinfo)) + self.register_instruction(cil.CILTypeName(vlocal, vlocal)) + self.register_instruction(cil.CILReturnNode(vlocal)) + + typename_func = cil.CILFunctionNode(MethodInfo(self.build_funcname('type_name'), vmholder= 4, returnType='String'), self.arguments, self.localvars, self.instructions) + self.register_function(typename_func) + + methods = {'ctor': ctor_func, 'abort':abort_func, 'type_name': typename_func} + # methods = {'ctor': ctor_func, 'type_name': typename_func} + cinfo = ClassInfo('Object', 4*len(attrs.keys()), 4*len(methods.keys())) + return cil.CILTypeNode(cinfo, attrs, methods) + + def int_bi(self, object_type): + attrs = {'value': VariableInfo('value', vmholder=1)} + methods = copy(object_type.methods) + cinfo = ClassInfo('Int', 4*len(attrs.keys()), 4*len(methods.keys()), object_type) + return cil.CILTypeNode(cinfo, attrs, methods) + + def bool_bi(self, object_type): + attrs = {'value': VariableInfo('value', vmholder=1)} + methods = copy(object_type.methods) + cinfo = ClassInfo('Bool', 4*len(attrs.keys()), 4*len(methods.keys()), object_type) + return cil.CILTypeNode(cinfo, attrs, methods) + + def string_bi(self, object_type): + attrs = {'value': VariableInfo('value', vmholder=1)} + methods = copy(object_type.methods) + + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1)), cil.CILArgNode(VariableInfo('string2', vmholder=2))] + + vlocal1 = self.define_internal_local() + self.register_instruction(cil.CILGetAttribNode(vlocal1, self.arguments[0].vinfo, attrs['value'].vmholder)) + + vlocal2 = self.define_internal_local() + self.register_instruction(cil.CILConcatNode(vlocal2, vlocal1, self.arguments[1].vinfo)) + + # self.register_instruction(cil.CILSetAttribNode(self.arguments[0].vinfo, 'value', vlocal2)) + self.register_instruction(cil.CILReturnNode(vlocal2)) + + concat_func = cil.CILFunctionNode(MethodInfo(self.build_funcname('concat'), paramsType = ['String'], returnType='String'), self.arguments, self.localvars, self.instructions) + self.register_function(concat_func) + + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1))] + + v_local3 = self.define_internal_local() + self.register_instruction(cil.CILGetAttribNode(v_local3, self.arguments[0].vinfo, attrs['value'].vmholder)) + + v_local4 = self.define_internal_local() + self.register_instruction(cil.CILLengthNode(v_local4, v_local3)) + + self.register_instruction(cil.CILReturnNode(v_local4)) + + length_func = cil.CILFunctionNode(MethodInfo(self.build_funcname('length'), returnType='Int'), self.arguments, self.localvars, self.instructions) + self.register_function(length_func) + + + # Substring + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1)), cil.CILArgNode(VariableInfo('i', vmholder=2)), cil.CILArgNode(VariableInfo('l', vmholder=3))] + + label_val = self.build_label() + label_nval = self.build_label() + label_fin = self.build_label() + + label_nval1 = self.build_label() + label_fin1 = self.build_label() + + label_nval2 = self.build_label() + label_fin2 = self.build_label() + + vvar2 = self.define_internal_local() + self.register_instruction(cil.CILAssignNode(vvar2, 0)) + + vvar1 = self.define_internal_local() + self.register_instruction(cil.CILLessThan(vvar1, self.arguments[1].vinfo, vvar2)) + self.register_instruction(cil.CILGotoIfNode(vvar1, label_nval1)) + + self.register_instruction(cil.CILLessThan(vvar1, self.arguments[2].vinfo, vvar2)) + self.register_instruction(cil.CILGotoIfNode(vvar1, label_nval2)) + + self.register_instruction(cil.CILGotoIfNode(self.arguments[2].vinfo, label_val)) + + self.register_instruction(cil.CILGotoNode(label_nval)) + + self.register_instruction(label_val) + v_local5 = self.define_internal_local() + self.register_instruction(cil.CILGetAttribNode(v_local5, self.arguments[0].vinfo, attrs['value'].vmholder)) + + vhalt = self.define_internal_local() + vlength = self.define_internal_local() + self.register_instruction(cil.CILLengthNode(vlength, v_local5)) + + vsum = self.define_internal_local() + self.register_instruction(cil.CILPlusNode(vsum, self.arguments[1].vinfo, self.arguments[2].vinfo)) + self.register_instruction(cil.CILMinusNode(vsum, vsum, 1)) + self.register_instruction(cil.CILLessThan(vhalt, vsum, vlength)) + + label1 = self.build_label() + labelerror = self.build_label() + labelend = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(vhalt, label1)) + self.register_instruction(cil.CILGotoNode(labelerror)) + + self.register_instruction(label1) + + v_local6 = self.define_internal_local() + self.register_instruction(cil.CILSubstringNode(v_local6, v_local5, self.arguments[1].vinfo, self.arguments[2].vinfo)) + self.register_instruction(cil.CILReturnNode(v_local6)) + + self.register_instruction(cil.CILGotoNode(labelend)) + + self.register_instruction(labelerror) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_5'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(labelend) + self.register_instruction(cil.CILGotoNode(label_fin)) + + self.register_instruction(label_nval) + msg = self.register_data("") + var = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var, msg)) + self.register_instruction(cil.CILReturnNode(var)) + + self.register_instruction(label_fin) + self.register_instruction(cil.CILGotoNode(label_fin2)) + + self.register_instruction(label_nval2) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_5'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(label_fin2) + self.register_instruction(cil.CILGotoNode(label_fin1)) + + self.register_instruction(label_nval1) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_5'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(label_fin1) + + + substr_func = cil.CILFunctionNode(MethodInfo(self.build_funcname('substr'), paramsType = ['Int', 'Int'], returnType='String'), self.arguments, self.localvars, self.instructions) + self.register_function(substr_func) + + length_func.finfo.vmholder = len(methods.keys())+2 + methods['length'] = length_func + concat_func.finfo.vmholder = len(methods.keys())+2 + methods['concat'] = concat_func + substr_func.finfo.vmholder = len(methods.keys())+2 + methods['substr'] = substr_func + + cinfo = ClassInfo('String', 4*len(attrs.keys()), 4*len(methods.keys()), object_type) + return cil.CILTypeNode(cinfo, attrs, methods) + + def io_bi(self, object_type): + attrs = {} + methods = copy(object_type.methods) + + # Print string + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1)), cil.CILArgNode(VariableInfo('x', vmholder=2))] + + self.register_instruction(cil.CILPrintStrNode(self.arguments[1].vinfo)) + + # v_local1 = self.define_internal_local() + self.register_instruction(cil.CILReturnNode(self.arguments[0].vinfo)) + out_string = cil.CILFunctionNode(MethodInfo(self.build_funcname('out_string'), paramsType = ['String'], returnType='IO'), self.arguments, self.localvars, self.instructions) + self.register_function(out_string) + + # Print int + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1)), cil.CILArgNode(VariableInfo('x', vmholder=2))] + + self.register_instruction(cil.CILPrintIntNode(self.arguments[1].vinfo)) + + # v_local1 = self.define_internal_local() + self.register_instruction(cil.CILReturnNode(self.arguments[0].vinfo)) + out_int = cil.CILFunctionNode(MethodInfo(self.build_funcname('out_int'), paramsType = ['Int'], returnType='IO'), self.arguments, self.localvars, + self.instructions) + self.register_function(out_int) + + # Read string + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1))] + + v_local = self.define_internal_local() + self.register_instruction(cil.CILReadStrNode(v_local)) + self.register_instruction(cil.CILReturnNode(v_local)) + + in_string = cil.CILFunctionNode(MethodInfo(self.build_funcname('in_string'), returnType='String'), self.arguments, self.localvars, + self.instructions) + self.register_function(in_string) + + # Read int + self.change_current_function() + self.arguments = [cil.CILArgNode(VariableInfo('self', vmholder=1))] + + v_local = self.define_internal_local() + self.register_instruction(cil.CILReadIntNode(v_local)) + self.register_instruction(cil.CILReturnNode(v_local)) + + in_int = cil.CILFunctionNode(MethodInfo(self.build_funcname('in_int'), returnType='Int'), self.arguments, self.localvars, + self.instructions) + self.register_function(in_int) + + out_string.finfo.vmholder = len(methods.keys())+2 + methods['out_string'] = out_string + out_int.finfo.vmholder = len(methods.keys())+2 + methods['out_int'] = out_int + in_string.finfo.vmholder = len(methods.keys())+2 + methods['in_string'] = in_string + in_int.finfo.vmholder = len(methods.keys())+2 + methods['in_int'] = in_int + + cinfo = ClassInfo('IO', 4*len(attrs.keys()), 4*len(methods.keys()), object_type) + return cil.CILTypeNode(cinfo, attrs, methods) \ No newline at end of file diff --git a/src/compiler.py b/src/compiler.py new file mode 100644 index 00000000..81fbfd19 --- /dev/null +++ b/src/compiler.py @@ -0,0 +1,97 @@ +from sys import argv + +from lexer import make_lexer +import my_parser + +import type_checker +import type_builder +import type_collector + +import cil_types +import cool_to_cil + +import mips + +tokens = "" + + + +def main(): + args = argv + + cool_program_code = "" + + # Name of the file + #p = args[2] + p = args[1] + print(str(p)) + if not str(p).endswith(".cl"): + print("Cool program files must end with a \`.cl\` extension.\r\n") + exit(1) + + if True: + with open(str(p)) as file: + while True: + i = file.read(1) + if not(i): + break + if i == '\0': + cool_program_code += r'\0' + else: + cool_program_code += i + s = cool_program_code + + lexer, errors = make_lexer(cool_program_code) + if len(errors) > 0: + for er in errors: + print(er) + exit(1) + + + ast, errors = my_parser.parse(s) + + if len(errors) > 0: + for er in errors: + print(er) + exit(1) + + #recolectar los tipos + _type_collector = type_collector.TypeCollectorVisitor() + _type_collector.visit(ast, errors) + if len(errors) > 0: + for er in errors: + print(er) + exit(1) + + #construir los tipos + _type_builder = type_builder.TypeBuilderVisitor(_type_collector.Context) + _type_builder.visit(ast, errors) + if len(errors) > 0: + for er in errors: + print(er) + exit(1) + + #chequear tipos + _type_checker = type_checker.TypeCheckerVisitor() + _type_checker.visit(ast, _type_builder.context, errors) + if len(errors) > 0: + for er in errors: + print(er) + exit(1) + + _cil_types = cil_types.CILTypes( _type_builder.context.Hierarchy) + ast2 = _cil_types.visit(ast) + + + _cool_to_cil_visitor = cool_to_cil.COOLToCILVisitor(ast2) + cil_ast = _cool_to_cil_visitor.visit(ast) + + file_name = p[:-3] + '.mips' + myfile = open(file_name, 'w') + _mips = mips.VisitorMIPS() + res = _mips.visit(cil_ast) + myfile.write(res) + myfile.close() + +if __name__ == "__main__": + main() diff --git a/src/context.py b/src/context.py new file mode 100644 index 00000000..86fee7c8 --- /dev/null +++ b/src/context.py @@ -0,0 +1,510 @@ + +class Type: + def __init__(self,className,parent): + self.Name = className + self.AttrList = [Attribute("self",self)] + self.MethList = {} + self.Default = "void" + self.Parent = parent + self.Children = [] + + def DefineAttr(self, attr_name, attr_type): + if self.__IsDefineAttr(attr_name, self) is None: + attr = Attribute(attr_name, attr_type) + self.AttrList.append(attr) + return attr + else: + return None + + def __IsDefineAttr(self, attr_name, _type): + for attr in _type.AttrList: + if attr.Name == attr_name: + return attr + return None + #Verificar que no hay attr con el mismo nombre en los ancestros + # parent = _type.Parent + # if parent is None or not isinstance(parent, Type): + # return None + # else: + # return self.__IsDefineAttr(attr_name, parent) + + def IsDefineAttr2(self,attr_name, _type): + for attr in _type.AttrList: + if attr.Name == attr_name: + return attr + parent = _type.Parent + if parent is None or not isinstance(parent, Type): + return None + else: + return self.IsDefineAttr2(attr_name, parent) + + + def DefineMeth(self, meth_name, params_name, params_type, return_type, rename, context): + if (self.__IsDefineMeth(meth_name, params_type, return_type)): + return None + else: + self.MethList[meth_name] = Method(meth_name, params_name, params_type, return_type, rename, context) + return self.MethList[meth_name] + + + + + def DefineInHierarchy(self, attr_name): + for attr in self.AttrList: + if attr.Name == attr_name: + return True + _type = self.Parent + if (self.Parent == None): + return False + return _type.DefineInHierarchy(attr_name) + + + + def __IsDefineMeth(self, meth_name, params_type, return_type): + for meth in self.MethList: + if (meth == meth_name and params_type == self.MethList[meth].ParamsType and self.MethList[meth].ReturnType == return_type): + return True + + def __IsDefineMethParent(self, meth_name, params_type, return_type): + type = self.Parent + if (self.Parent == None): + return False + else: + return self.Parent.__IsDefineMeth(meth_name, params_type, return_type) + + def GetMethodReturnType(self, meth_name): + if (meth_name in self.MethList.keys): + return self.MethList[meth_name].ReturnType + if (self.Parent is None): + return None + return self.Parent.GetMethodReturnType(meth_name) + + def GetAttr(self, attr_name): + for attr in self.AttrList: + if (attr.Name == attr_name): + return attr + if (self.Parent is None): + return None + return self.Parent.GetAttr(attr_name) + + def GetMeth(self, meth_name, params_type): + for meth in self.MethList: + if (self.MethList[meth].Name == meth_name and len(params_type) == len(self.MethList[meth].ParamsType)): + for x in range(len(self.MethList[meth].ParamsType)): + if (not self.MethList[meth].ParamsType[x] == params_type[x]): + return None + return self.MethList[meth] + parent = self.Parent + if (parent is None): + return None + else: + return parent.GetMeth(meth_name, params_type, return_type) + +class Attribute: + def __init__(self, attr_name, attr_type): + self.Name = attr_name + self.Type = attr_type + +class Method: + def __init__(self,meth_name, params_name, params_type,return_type, rename, context): + self.Name = meth_name + self.ReturnType = return_type + self.ParamsName = params_name + self.ParamsType = params_type + self.rename = rename + self.Context = context + +class Variable: + def __init__(self, var_name, var_type, value = None): + self.Name = var_name + self.Type = var_type + self.Value = value + +class Context: + def __init__(self, parent): + self.Variables = {} #nombre de la variable, su tipo + self.Parent = parent + self.Children = [] + self.CurrentClass = None + + if parent is None: + self.buildin = self.__GetBuildIn() + self.OrderClasses = [] + + def IsDefineMeth2(self, ctype, meth_name): + if ctype is None: + return None + # la clase tiene ese metodo??? + if not ctype.MethList.keys().__contains__(meth_name): + #preguntar si el padre tiene ese meth + parent = ctype.Parent + return self.IsDefineMeth2(parent,meth_name) + return ctype.MethList[meth_name] + + def IsDefineMeth(self,ctype, meth_name, params_type, return_type): + if ctype is None: + return None + myctype = self.Hierarchy[ctype] + # la clase tiene ese metodo??? + if not myctype.MethList.keys().__contains__(meth_name): + #preguntar si el padre tiene ese meth + parent = myctype.Parent + return self.IsDefineMeth(parent,meth_name, params_type, return_type) + meth = myctype.MethList[meth_name] + if not (len(params_type)== len(meth.ParamsType)): + return None + for i,param in enumerate(params_type): + if not (meth.ParamsType[i] == param) and (not self.IsDerived(param,meth.ParamsType[i])): + return None + + def __GetBuildIn(self): + self.Hierarchy = {} + typeObject = Type("Object",parent = None) + self.Hierarchy["Object"] = typeObject + + + + typeString = Type("String",typeObject) + # typeObject = Type("Object",self.Hierarchy["Object"]) + typeBool = Type("Bool",typeObject) + typeInt = Type("Int",typeObject) + typeIO = Type("IO",typeObject) + + self.Hierarchy["String"] = typeString + self.Hierarchy["Bool"] = typeBool + self.Hierarchy["Int"] = typeInt + self.Hierarchy["IO"] = typeIO + self.Hierarchy["error"] = Type("error", typeObject) + + typeObject.MethList["abort"] = (Method("abort",[],[],"Object",None,self)) + typeObject.MethList["type_name"] =(Method("type_name",[],[],"String",None, self)) + + typeIO.MethList["in_string"] =(Method("in_string",[],[],"String",None, self)) + typeIO.MethList["in_int"] =(Method("in_int",[],[],"Int",None, self)) + child_context = self.CreateChildContext() + child_context.DefineVar("x","String") + typeIO.MethList["out_string"] = (Method("out_string", ["x"], ["String"], "IO", None, child_context)) + child_context = self.CreateChildContext() + child_context.DefineVar("x", "Int") + typeIO.MethList["out_int"] = (Method("out_int", ["x"], ["Int"], "IO", None, child_context)) + + + typeString.MethList["length"] =(Method("length",[],[],"Int",None, self)) + child_context = self.CreateChildContext() + child_context.DefineVar("s", "String") + typeString.MethList["concat"] =(Method("concat",["s"],["String"],"String",None, child_context)) + child_context = self.CreateChildContext() + child_context.DefineVar("i", "Int") + child_context.DefineVar("l", "Int") + typeString.MethList["substr"] =(Method("substr",["i","l"],["Int","Int"],"String",None, child_context)) + + + typeInt.default = 0 + typeBool.default = "false" + typeString.default = "" + + typeObject.MethList["type_name"].ComputedType = [self.GetType("String")] + typeObject.MethList["abort"].ComputedType = [self.GetType("Object")] + + typeIO.MethList["out_int"].ComputedType = [self.GetType("IO")] + typeIO.MethList["in_string"].ComputedType = [self.GetType("String")] + typeIO.MethList["in_int"].ComputedType = [self.GetType("Int")] + typeIO.MethList["out_string"].ComputedType = [self.GetType("IO")] + + typeString.MethList["substr"].ComputedType = [self.GetType("String")] + typeString.MethList["length"].ComputedType = [self.GetType("Int")] + typeString.MethList["concat"].ComputedType = [self.GetType("String")] + + return [typeString,typeBool,typeInt] + + def GetMethodReturnType(self, meth_name, params_type): + myctype = self.Hierarchy[ctype] + meth = myctype.GetMethodReturnType(methodName) + if meth == None: + return None + if not (len(paramsType)== len(meth.paramsType)): + return None + for i,param in enumerate(paramsType): + if not (meth.paramsType[i] == param) and (not self.IsDerived(param,meth.paramsType[i])): + return None + return meth.returnType + + def GetType(self,typeName): # devuelve el objeto + for _type in self.Hierarchy.keys(): + if _type == typeName: + return self.Hierarchy[typeName] + return None + + def MostDefineType(self,typeName): + return (not self.Hierarchy.__contains__(typeName)) + + def DefineType(self, type_name, type_parent): + if self.MostDefineType(type_name): + t = Type(type_name, type_parent) + self.Hierarchy[type_name] = t + return t + else: + return None + + + def DefineVar(self, var_name, var_type, value = None): + if (self.__IsDefineVar(var_name, var_type) is None): + v = Variable(var_name, var_type, value) + self.Variables[var_name] = v + return v + else: + return None + + def __IsDefineVar(self, var_name, var_type): + if (var_name in self.Variables.keys()): + v = self.Variables[var_name] + return v.Type + return None + + + def LinkTypes(self,errors): + values = list(self.Hierarchy.values()) + # for item in values: + # print(item.name) + # print("values1",values1) + # a = self.Hierarchy["String"] + # print("a",a.name) + # values = values1.remove(a) + # print("values",values) + for item in values: + # print("item.name",item.name) + # print("item.parent",item.parent) + if not (item.parent == None): + # print("item.parent1",item.parent) + parent = self.GetType(item.parent) + # print("here",parent) + if parent == None: + errors.append("(0,0) - TypeError: El tipo "+ item.parent + " no esta definido") + return False + item.parent = parent + parent.children.append(item) + + return self.IsValid(errors) + # return True + + def IsDerived(self, derived, ancestor): + # print("derived,ancestor",derived,ancestor) + derivedType = self.GetType(derived) + return self._IsDerived(derivedType,ancestor) + + def _IsDerived(self, derived, ancestor): + # print("derived,ancestor1",derived.name,ancestor) + derivedparent = derived.Parent + if derivedparent == None: + return False + if derivedparent.Name == ancestor: + return True + return self._IsDerived(derivedparent,ancestor) + + def IsValid(self,errors): #revisar q no haya ciclos + for item in self.buildin: + if len(item.children): + errors.append("(0,0) - SemanticError: No se puede heredar del metodo "+ item.name) + # print("buildin con hijos " + item.name) + return False + return self.NotExistCicle(errors) + + def NotExistCicle(self,errors): + # self.order_classes = [] + self._NotExistCicle( self.Hierarchy["Object"],self.order_classes) + # print("No Hay ciclo", len(self.order_classes) == len(self.Hierarchy)) + # print(self.order_classes) + if len(self.order_classes) == len(self.Hierarchy): + self.sorted = self.order_classes + return True + errors.append("(0,0) - SemanticError: No pueden existir ciclos en la herencia") + return False + # return len(self.order_classes) == len(self.Hierarchy) + + def _NotExistCicle(self, a: Type, types: list): + # print("aciclicos",a.name) + if a is None: + return True + if types.__contains__(a.name): + return False + types.append(a.name) + + for child in a.children: + if not self._NotExistCicle(child, types): + return False + return True + + def NotIOReimplemetation(self): + # print("------------") + + # print("HOLA") + io = self.Hierarchy["IO"] + succ = io.children + # print("----cosita",io.children) + # print("----cosita2",io.children[0].MethList) + # print("succ ", succ) + while len(succ): + item = succ.pop() + # print("metodos", item.MethList.values()) + for m in item.MethList.values(): + if m.name == "in_string" or m.name == "in_int" or m.name == "out_string" or m.name == "out_int": + return False + succ = succ + item.children + + # print("------------") + return True + + def LCA(self,a: Type, b: Type): + # Si son iguales + if a.name == b.name: + return a.name + + # Lista de los posibles ancestros + ancestors = [] + + # Voy subiendo hasta llegar a la raíz y guardando los nodos.name que son los ancestros de a + while a is not None: + ancestors.append(a.name) + a = a.parent + + # Trato de encontrar un ancestro de b que sea ancestro de a, el cual será el LCA + # b = b.parent + while b is not None: + if ancestors.__contains__(b.name): + return b.name + b = b.parent + + return None + + def _GetType(self, vname): + var = self.variables.get(vname) + if var == None: + return None + return var.ctype + + def GetVinfo(self,vname): + # print("is def var") + var = self.variables.get(vname) + if not (var == None): + # print("contain",vname) + return var + if self.parent == None: + return None + # print("parent") + return self.parent.GetVinfo(vname) + + def IsDefineVariable(self,vname): + vinfo = self.GetVinfo(vname) + if vinfo == None: + vtype = self.Hierarchy[self.CurrentClass]._IsDefineAttributeInParent(vname) + if vtype == None: + return None + return vtype + return vinfo.ctype + + def CreateChildContext(self): + childContext = Context(self) + childContext.Hierarchy = self.Hierarchy + childContext.CurrentClass = self.CurrentClass + for var in self.Variables.keys(): + childContext.Variables[var] = self.Variables[var] + return childContext + + def BuildTypesHierarchy(self): + ''' + directed graph + ''' + graph = {} + for _type in self.Hierarchy: + graph[_type] = [] + for _type in self.Hierarchy: + if _type != "Object": + u = self.Hierarchy[_type].Parent.Name + v = self.Hierarchy[_type].Name + graph[u].append(v) + self.inheritance_graph = graph + + def CheckMain(self): + _type = self.GetType("Main") + if _type is not None: # checking if there is the program has a class Main + method = _type.GetMeth("main", []) # the method main is not inherited because enviroment is None + if method is None: # checking if the a class Main has a method named main + #error + pass + if len(method.ParamsName) > 0: # checking if the method main takes no formal parameters + #error + pass + #retorno + pass + else: + #error + pass + + def IsTree(self, errors): + #self.build_types_graph() + self.visited = {} + for u in self.Hierarchy: + self.visited[u] = False + for u in self.Hierarchy: + if not self.visited[u]: + if self.dfs_cycles(u): + errors.append("SemanticError: Class " + u + ", or an ancestor of " + u + ", is involved in an inheritance cycle.") + return 0 + return 1 + + def dfs_cycles(self, u): + self.visited[u] = True + for v in self.inheritance_graph[u]: + if self.visited[v]: + return True + if self.dfs_cycles(v): + return True + return False + + def GetAttr(self, _type, lex): + for _var in self.Variables.keys(): + if (_var == lex): + return self.Variables[_var] + return self.__GetAttr(_type, lex) + + + def __GetAttr(self,_type, lex): + for _var in _type.AttrList: + if (_var.Name == lex): + return _var + parent = _type.Parent + if parent is None: + return None + else: + return self.__GetAttr(parent, lex) + +class VariableInfo: + def __init__(self, name, ctype = None, vmholder = 0): + self.name = name + self.ctype = ctype + self.vmholder = vmholder + + def __str__(self): + return " name: " + str(self.name) + ", tipo: "+ str(self.ctype) + ", vmholder: " + str(self.vmholder) + +class MethodInfo: + def __init__(self, name, vmholder = 0, paramsType = [], returnType = None): + self.name = name + self.vmholder = vmholder + self.paramsType = paramsType + self.returnType = returnType + + def __str__(self): + return " name: " + str(self.name) + ", vmholder: " + str(self.vmholder) + +class ClassInfo: + def __init__(self, name, attr_length = 0, meth_length = 0, parent = None): + self.name = name + self.attr_length = attr_length + self.meth_length = meth_length + self.parent = parent + + def __str__(self): + return " name: " + str(self.name) + " parent: " + str(self.parent.cinfo.name) + ", attr_length: " + str(self.attr_length) + ", meth_length: " + str(self.meth_length) + + diff --git a/src/cool_to_cil.py b/src/cool_to_cil.py new file mode 100644 index 00000000..ca4984f3 --- /dev/null +++ b/src/cool_to_cil.py @@ -0,0 +1,785 @@ +import ast_hierarchy as ast +import cil_hierarchy as cil +import visitor +from context import VariableInfo, MethodInfo +from copy import copy + + +class COOLToCILVisitor: + def __init__(self, programnode:cil.CILProgramNode): + self.programnode = programnode + + # La sección .TYPES del CIL + self.dottypes = {} + # La sección .DATA del CIL + self.dotdata = {} + # La sección .CODE del CIL + self.dotcode = [] + + self.current_class = None + + self.current_function = None + + # Variables locales del método actual + self.localvars = [] + + # Instrucciones del método actual + self.instructions = [] + + # Parametros del metodo actual + self.arguments = [] + + self.internal_count = 0 + + self.void = 0 + + # Util Methods + def change_current_function(self, current_func): + self.current_function = current_func + self.localvars = current_func.localvars + self.instructions = current_func.instructions + self.arguments = current_func.arguments + + def define_internal_local(self): + vinfo = VariableInfo('internal') + vinfo.name = self.build_internal_vname(vinfo.name) + return self.register_local(vinfo) + + def build_internal_vname(self, vname): + vname = '{}_{}'.format(vname, self.internal_count) + self.internal_count += 1 + return vname + + def build_label(self): + fname = 'label_{}'.format(self.internal_count) + self.internal_count += 1 + return cil.CILLabelNode(fname) + + def register_local(self, vinfo): + vinfo.vmholder = len(self.localvars) + len(self.arguments)+1 + local_node = cil.CILLocalNode(vinfo) + self.localvars.append(local_node) + return local_node.vinfo + + def register_instruction(self, instruction): + self.instructions.append(instruction) + + def register_argument(self, vinfo): + vinfo.vmholder = len(self.arguments)+1 + argum = cil.CILArgNode(vinfo) + self.arguments.append(argum) + return argum.vinfo + + def register_data(self, value): + vname = 'data_{}'.format(len(self.dotdata)) + data_node = cil.CILDataNode(vname, value) + self.dotdata[vname] = data_node + return data_node + + def _boxing(self, vinfo, ctype): + vlocal = self.define_internal_local() + self.register_instruction(cil.CILAllocateNode(vlocal, self.dottypes[ctype].cinfo)) + # t_local = self.define_internal_local() + # self.register_instruction(cil.CILTypeOfNode(t_local, vlocal)) + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(vlocal)) + useless = self.define_internal_local() + fname = self.dottypes[ctype].methods['ctor'].finfo.name + self.register_instruction(cil.CILStaticCallNode(useless, fname)) + num2 = self.dottypes[ctype].attrs['value'].vmholder + self.register_instruction(cil.CILSetAttribNode(vlocal, num2, vinfo)) + return vlocal + + def _ifboxing(self, vvar, cond): + vret = vvar + if cond == 'String' or cond == 'Int' or cond == 'Bool': + vret = self._boxing(vvar, cond) + return vret + + def _ifobjectboxing(self, vvar, cond1, cond2): + vret = vvar + if (cond1 == 'String' or cond1 == 'Int' or cond1 == 'Bool') and cond2 == 'Object': + vret = self._boxing(vvar, cond1) + return vret + + # Visit + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(ast.ProgramNode) + def visit(self, node: ast.ProgramNode): + # print("------------visit node: ProgramNode") + self.dottypes = self.programnode.dottypes + self.dotcode = self.programnode.dotcode + self.dotdata = self.programnode.dotdata + + for child in node.classes: + self.visit(child) + + return self.programnode + + @visitor.when(ast.ClassNode) + def visit(self, node: ast.ClassNode): + # print("------------visit node: CoolClass") + self.current_class = self.dottypes[node.typeName] + parent_class = self.current_class.cinfo.parent + + self.change_current_function(self.current_class.methods['ctor']) + self.register_argument(VariableInfo('self')) + + useless = self.define_internal_local() + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(self.arguments[0].vinfo)) + name = parent_class.methods['ctor'].finfo.name + self.register_instruction(cil.CILStaticCallNode(useless, name)) + + + for feature in node.features: + if isinstance(feature, ast.AttributeFeatureNode): + self.visit(feature) + + self.register_instruction(cil.CILReturnNode()) + + for feature in node.features: + if isinstance(feature, ast.FunctionFeatureNode): + self.visit(feature) + + @visitor.when(ast.AttributeFeatureNode) + def visit(self, node: ast.AttributeFeatureNode, dest = None): + # si es un attributo de la clase + if self.current_class.attrs.__contains__(node.id): + var_self = self._find('self') + vlocal = self.define_internal_local() + self.visit(node.expression, vlocal) + num = self.current_class.attrs[node.id].vmholder + self.register_instruction(cil.CILSetAttribNode(var_self, num, vlocal)) + #si es un atributo interno de un statement + else: + node.vinfo = VariableInfo(node.id, node.typeName) + vlocal = self.register_local(node.vinfo) + if node.id == 'self': + v_self = self._find('self') + self.register_instruction(cil.CILAssignNode(dest, v_self)) + elif not node.vinfo in [a.vinfo for a in self.localvars] and not node.vinfo in [a.vinfo for a in self.arguments]: + v_self = self._find('self') + num = self.dottypes[self.current_class.cinfo.name].attrs[node.id].vmholder + self.register_instruction(cil.CILGetAttribNode(dest, v_self, num)) + else: + self.register_instruction(cil.CILAssignNode(dest, node.vinfo)) + + + + + @visitor.when(ast.FunctionFeatureNode) + def visit(self, node: ast.FunctionFeatureNode): + # print("------------visit node: Method") + self.change_current_function(self.dottypes[self.current_class.cinfo.name].methods[node.id]) + + self.register_argument(VariableInfo('self')) + for param in node.parameters: + self.register_argument(param.vinfo) + + ret_var = self.define_internal_local() + self.visit(node.statements, ret_var) + # print("///////////tipo retorno", self.current_function.finfo.returnType) + # print("////////////tipo", node.exprbody.typeName) + var_box = self._ifobjectboxing(ret_var, node.statements.typeName, self.current_function.finfo.returnType) + self.register_instruction(cil.CILReturnNode(var_box)) + + @visitor.when(ast.PlusNode) + def visit(self, node: ast.PlusNode, dest): + # print("------------visit node: PlusNode") + left = self.define_internal_local() + self.visit(node.left, left) + + right = self.define_internal_local() + self.visit(node.right, right) + self.register_instruction(cil.CILPlusNode(dest, left, right)) + + @visitor.when(ast.MinusNode) + def visit(self, node: ast.MinusNode, dest): + # print("------------visit node: MinusNode") + left = self.define_internal_local() + self.visit(node.left, left) + + right = self.define_internal_local() + self.visit(node.right, right) + self.register_instruction(cil.CILMinusNode(dest, left, right)) + + @visitor.when(ast.TimesNode) + def visit(self, node: ast.TimesNode, dest): + # print("------------visit node: StarNode") + left = self.define_internal_local() + self.visit(node.left, left) + + right = self.define_internal_local() + self.visit(node.right, right) + self.register_instruction(cil.CILStarNode(dest, left, right)) + + @visitor.when(ast.DivideNode) + def visit(self, node: ast.DivideNode, dest): + # print("------------visit node: DivNode") + left = self.define_internal_local() + self.visit(node.left, left) + + right = self.define_internal_local() + self.visit(node.right, right) + + label1 = self.build_label() + labelerror = self.build_label() + labelend = self.build_label() + + vhalt = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(vhalt, right, 0)) + self.register_instruction(cil.CILGotoIfNode(vhalt, label1)) + self.register_instruction(cil.CILGotoNode(labelerror)) + + self.register_instruction(label1) + + self.register_instruction(cil.CILDivNode(dest, left, right)) + self.register_instruction(cil.CILGotoNode(labelend)) + + self.register_instruction(labelerror) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_4'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(labelend) + + @visitor.when(ast.ComplementNode) + def visit(self, node: ast.ComplementNode, dest): + # print("------------visit node: Neg") + right = self.define_internal_local() + self.visit(node.expr, right) + self.register_instruction(cil.CILMinusNode(dest, 0, right)) + + @visitor.when(ast.NotNode) + def visit(self, node: ast.NotNode, dest): + # print("------------visit node: Not") + right = self.define_internal_local() + self.visit(node.expr, right) + self.register_instruction(cil.CILMinusNode(dest, 1, right)) + + @visitor.when(ast.LetStatementNode) + def visit(self, node: ast.LetStatementNode, dest): + # print("------------visit node: Let") + #hacr el visit + for item in node.variables: + self.visit(item, dest) + + self.visit(node.expression, dest) + + # @visitor.when(ast.Declaration) + # def visit(self, node: ast.Declaration): + # # print("------------visit node: Declaration") + # vlocal = self.register_local(node.vinfo) + # ret_var = self.define_internal_local() + # self.visit(node.expr, ret_var) + # vbox = self._ifobjectboxing(ret_var, node.expr.typeName, node.vinfo.ctype) + # self.register_instruction(cil.CILAssignNode(vlocal, vbox)) + # return vlocal + + @visitor.when(ast.BlockStatementNode) + def visit(self, node: ast.BlockStatementNode, dest): + # print("------------visit node: Block") + last = None + for expr in node.expressions: + vlocal = self.define_internal_local() + last = vlocal + self.visit(expr, vlocal) + self.register_instruction(cil.CILAssignNode(dest, last)) + + @visitor.when(ast.AssignStatementNode) + def visit(self, node: ast.AssignStatementNode, dest): + # print("------------visit node: Assignment") + v_temp = self.define_internal_local() + self.visit(node.id, v_temp) + self.visit(node.expression, v_temp) + # print("................. node.id.vinfo",node.id.typeName) + v_box = self._ifobjectboxing(v_temp, node.expression.typeName, node.id.typeName) + + if not node.id.vinfo in [a.vinfo for a in self.localvars] and not node.id.vinfo in [a.vinfo for a in self.arguments]: + v_self = self._find('self') + num = self.dottypes[self.current_class.cinfo.name].attrs[node.id.name].vmholder + self.register_instruction(cil.CILSetAttribNode(v_self, num, v_box)) + self.register_instruction(cil.CILGetAttribNode(dest, v_self, num)) + else: + self.register_instruction(cil.CILAssignNode(node.id.vinfo, v_box)) + self.register_instruction(cil.CILAssignNode(dest, node.id.vinfo)) + + @visitor.when(ast.ConstantStringNode) + def visit(self, node: ast.ConstantStringNode, dest): + msg = self.register_data(node.lex) + var = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var, msg)) + self.register_instruction(cil.CILAssignNode(dest, var)) + + @visitor.when(ast.ConstantBoolNode) + def visit(self, node: ast.ConstantBoolNode, dest): + var = 1 if node.value else 0 + self.register_instruction(cil.CILAssignNode(dest, var)) + + @visitor.when(ast.ConstantNumericNode) + def visit(self, node: ast.ConstantNumericNode, dest): + self.register_instruction(cil.CILAssignNode(dest, node.lex)) + + @visitor.when(ast.VariableNode) + def visit(self, node: ast.VariableNode, dest): + #crear su vinfo y definirlo en los locals + for local in self.localvars: + if local.vinfo.name == node.lex: + node.vinfo = local.vinfo + + + @visitor.when(ast.ConditionalStatementNode) + def visit(self, node: ast.ConditionalStatementNode, dest): + # print("------------visit node: Conditional") + if_eval = self.define_internal_local() + self.visit(node.ifexpr, if_eval) + + label_then = self.build_label() + label_end = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(if_eval, label_then)) + self.visit(node.elseexpr, dest) + self.register_instruction(cil.CILGotoNode(label_end)) + self.register_instruction(label_then) + self.visit(node.thenexpr, dest) + self.register_instruction(label_end) + + @visitor.when(ast.LoopStatementNode) + def visit(self, node: ast.LoopStatementNode, dest): + # print("------------visit node: Loop") + + cond_eval = self.define_internal_local() + + label_entry = self.build_label() + self.register_instruction(label_entry) + + self.visit(node.whileexpr, cond_eval) + + label_end = self.build_label() + label_loop = self.build_label() + self.register_instruction(cil.CILGotoIfNode(cond_eval, label_loop)) + self.register_instruction(cil.CILGotoNode(label_end)) + + self.register_instruction(label_loop) + + vbody = self.define_internal_local() + self.visit(node.loopexpr, vbody) + + self.register_instruction(cil.CILGotoNode(label_entry)) + self.register_instruction(label_end) + + self.register_instruction(cil.CILAssignNode(dest, self.void)) + + @visitor.when(ast.LessNode) + def visit(self, node: ast.LessNode, dest): + # print("------------visit node: LessThan") + vleft = self.define_internal_local() + vright = self.define_internal_local() + self.visit(node.left, vleft) + self.visit(node.right, vright) + rest = self.define_internal_local() + self.register_instruction(cil.CILLessThan(dest, vleft, vright)) + + @visitor.when(ast.LessEqualNode) + def visit(self, node: ast.LessEqualNode, dest): + # print("------------visit node:.LessEqualThan") + vleft = self.define_internal_local() + vright = self.define_internal_local() + self.visit(node.left, vleft) + self.visit(node.right, vright) + self.register_instruction(cil.CILPlusNode(vright, 1, vright)) + rest = self.define_internal_local() + self.register_instruction(cil.CILLessThan(dest, vleft, vright)) + + @visitor.when(ast.EqualNode) + def visit(self, node: ast.EqualNode, dest): + # print("------------visit node: Equal") + vleft = self.define_internal_local() + vright = self.define_internal_local() + self.visit(node.left, vleft) + self.visit(node.right, vright) + + if node.left.typeName == 'String': + + vlength_r = self.define_internal_local() + self.register_instruction(cil.CILLengthNode(vlength_r, vright)) + vlength_l = self.define_internal_local() + self.register_instruction(cil.CILLengthNode(vlength_l, vleft)) + + self.register_instruction(cil.CILMinusNode(dest, vlength_l, vlength_r)) + + label_loop = self.build_label() + label_loopbody = self.build_label() + label_equal = self.build_label() + label_notequal = self.build_label() + label_end = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(dest, label_notequal)) + + pos = self.define_internal_local() + self.register_instruction(cil.CILAssignNode(pos, 0)) + + self.register_instruction(label_loop) + self.register_instruction(cil.CILGotoIfNode(vlength_r, label_loopbody)) + + self.register_instruction(cil.CILGotoNode(label_equal)) + + self.register_instruction(label_loopbody) + cleft = self.define_internal_local() + cright = self.define_internal_local() + self.register_instruction(cil.CILGetIndexNode(cleft, vleft, pos)) + self.register_instruction(cil.CILGetIndexNode(cright, vright, pos)) + self.register_instruction(cil.CILMinusNode(vlength_r, vlength_r, 1)) + self.register_instruction(cil.CILPlusNode(pos, pos, 1)) + + vrest = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(vrest, cleft, cright)) + self.register_instruction(cil.CILGotoIfNode(vrest, label_notequal)) + + self.register_instruction(cil.CILGotoNode(label_loop)) + + self.register_instruction(label_equal) + self.register_instruction(cil.CILAssignNode(dest, 1)) + self.register_instruction(cil.CILGotoNode(label_end)) + + self.register_instruction(label_notequal) + self.register_instruction(cil.CILAssignNode(dest, 0)) + self.register_instruction(label_end) + + else: + rest = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(rest, vleft, vright)) + label_1 = self.build_label() + label_2 = self.build_label() + self.register_instruction(cil.CILGotoIfNode(rest, label_1)) + self.register_instruction(cil.CILAssignNode(dest, 1)) + self.register_instruction(cil.CILGotoNode(label_2)) + self.register_instruction(label_1) + self.register_instruction(cil.CILAssignNode(dest, 0)) + self.register_instruction(label_2) + + @visitor.when(ast.IsVoidNode) + def visit(self, node: ast.IsVoidNode, dest): + # print("------------visit node: IsVoid") + vlocal = self.define_internal_local() + self.visit(node.expr, vlocal) + v_box = self._ifboxing(vlocal, node.expr.typeName) + # self.register_instruction(cil.CILMinusNode(dest, self.void, v_box)) + + rest = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(rest, self.void, v_box)) + label_1 = self.build_label() + label_2 = self.build_label() + self.register_instruction(cil.CILGotoIfNode(rest, label_1)) + self.register_instruction(cil.CILAssignNode(dest, 1)) + self.register_instruction(cil.CILGotoNode(label_2)) + self.register_instruction(label_1) + self.register_instruction(cil.CILAssignNode(dest, 0)) + self.register_instruction(label_2) + + @visitor.when(ast.NewStatementNode) + def visit(self, node: ast.NewStatementNode, dest): + # print("------------visit node: New") + if node.newType == 'Int' or node.newType == 'Bool': + self.register_instruction(cil.CILAssignNode(dest, 0)) + + elif node.newType == 'String': + msg = self.register_data("") + var = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var, msg)) + self.register_instruction(cil.CILAssignNode(dest, var)) + + else: + self.register_instruction(cil.CILAllocateNode(dest, self.dottypes[node.newType].cinfo)) + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(dest)) + useless = self.define_internal_local() + # v_type = self.define_internal_local() + # self.register_instruction(cil.CILTypeOfNode(v_type, dest)) + fname = self.dottypes[node.newType].methods['ctor'].finfo.name + self.register_instruction(cil.CILStaticCallNode(useless, fname)) + + @visitor.when(ast.CaseStatementNode) + def visit(self, node: ast.CaseStatementNode, dest): + # print("------------visit node: Case") + vexpr = self.define_internal_local() + self.visit(node.case0, vexpr) + + vbox = self._ifboxing(vexpr, node.case0.typeName) + + vhalt = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(vhalt, self.void, vbox)) + + label1 = self.build_label() + labelerror = self.build_label() + labelend = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(vhalt, label1)) + self.register_instruction(cil.CILGotoNode(labelerror)) + + self.register_instruction(label1) + + texpr = self.define_internal_local() + self.register_instruction(cil.CILTypeOfNode(texpr, vbox)) + + expr_list = [self.visit(case) for case in node.exprList] + + label_init = self.build_label() + self.register_instruction(label_init) + + label_error = self.build_label() + + for tlocal, label_expr, _, _ in expr_list: + vinternal = self.define_internal_local() + # self.register_instruction(cil.CILMinusNode(vinternal, tlocal, texpr)) + + rest = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(rest, tlocal, texpr)) + label_1 = self.build_label() + label_2 = self.build_label() + self.register_instruction(cil.CILGotoIfNode(rest, label_1)) + self.register_instruction(cil.CILAssignNode(vinternal, 1)) + self.register_instruction(cil.CILGotoNode(label_2)) + self.register_instruction(label_1) + self.register_instruction(cil.CILAssignNode(vinternal, 0)) + self.register_instruction(label_2) + + # self.register_instruction(cil.CILMinusNode(vinternal, 1, vinternal)) + self.register_instruction(cil.CILGotoIfNode(vinternal, label_expr)) + + vobject = self.define_internal_local() + self.register_instruction(cil.CILAllocateNode(vobject, self.dottypes['Object'].cinfo)) + self.register_instruction(cil.CILTypeOfNode(vobject, vobject)) + vo_comp = self.define_internal_local() + # self.register_instruction(cil.CILMinusNode(vo_comp, vobject, texpr)) + + rest = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(rest, vobject, texpr)) + label_1 = self.build_label() + label_2 = self.build_label() + self.register_instruction(cil.CILGotoIfNode(rest, label_1)) + self.register_instruction(cil.CILAssignNode(vo_comp, 1)) + self.register_instruction(cil.CILGotoNode(label_2)) + self.register_instruction(label_1) + self.register_instruction(cil.CILAssignNode(vo_comp, 0)) + self.register_instruction(label_2) + + # self.register_instruction(cil.CILMinusNode(vo_comp, 1, vo_comp)) + self.register_instruction(cil.CILGotoIfNode(vo_comp, label_error)) + + tparent = self.define_internal_local() + self.register_instruction(cil.CILParentNode(tparent, texpr)) + self.register_instruction(cil.CILAssignNode(texpr, tparent)) + + self.register_instruction(cil.CILGotoNode(label_init)) + + label_end = self.build_label() + for _, label_expr, expr, vinternalocal in expr_list: + self.register_instruction(label_expr) + self.register_instruction(cil.CILAssignNode(vinternalocal, vexpr)) + resp = self.define_internal_local() + self.visit(expr, resp) + self.register_instruction(cil.CILAssignNode(dest, resp)) + self.register_instruction(cil.CILGotoNode(label_end)) + + self.register_instruction(label_error) + # self.register_instruction(cil.CILPrintStrNode(var1)) + var2 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var2, self.dotdata['exception_3'])) + self.register_instruction(cil.CILPrintStrNode(var2)) + self.register_instruction(cil.CILErrorNode()) + self.register_instruction(label_end) + + self.register_instruction(cil.CILGotoNode(labelend)) + + self.register_instruction(labelerror) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_2'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(labelend) + + @visitor.when(ast.CaseBranchNode) + def visit(self, node: ast.CaseBranchNode): + # print("------------visit node: CaseExpr") + vlocal = node.decl.vinfo + self.register_local(vlocal) + + ctype_ = vlocal.ctype + self.register_instruction(cil.CILAllocateNode(vlocal, self.dottypes[ctype_].cinfo)) + # vbox = self._ifboxing(vlocal, vlocal.ctype) + + tlocal = self.define_internal_local() + self.register_instruction(cil.CILTypeOfNode(tlocal, vlocal)) + + label = self.build_label() + return ((tlocal, label, node.expr, vlocal)) + + + @visitor.when(ast.FunctionCallStatement) + def visit(self, node: ast.FunctionCallStatement, dest): + if node.instance.lex == 'self': + params = [] + method_ = self.dottypes[self.current_class.cinfo.name].methods[node.function].finfo + vself = self._find('self') + + vhalt = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(vhalt, self.void, vself)) + + label1 = self.build_label() + labelerror = self.build_label() + labelend = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(vhalt, label1)) + self.register_instruction(cil.CILGotoNode(labelerror)) + + self.register_instruction(label1) + + for i, expr in enumerate(node.args): + vlocal = self.define_internal_local() + self.visit(expr, vlocal) + p = method_.paramsType[i] + + v_box = self._ifobjectboxing(vlocal, expr.typeName, p) + params.append(v_box) + + self.register_instruction(cil.CILSaveState()) + + self.register_instruction(cil.CILParamNode(vself)) + + for p in params: + self.register_instruction(cil.CILParamNode(p)) + + self.register_instruction(cil.CILStaticCallNode(dest, method_.name)) + self.register_instruction(cil.CILGotoNode(labelend)) + + self.register_instruction(labelerror) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_1'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(labelend) + elif not node.dispatchType is None: + params = [] + ctype_ = node.instance.typeName + method_ = self.dottypes[ctype_].methods[node.function].finfo + + for i, expr in enumerate(node.args): + vlocal = self.define_internal_local() + self.visit(expr, vlocal) + p = method_.paramsType[i] + + v_box = self._ifobjectboxing(vlocal, expr.typeName, p) + params.append(v_box) + + v_eval = self.define_internal_local() + self.visit(node.function, v_eval) + + v_box_eval = self._ifboxing(v_eval, node.typeName) + + vhalt = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(vhalt, self.void, v_box_eval)) + + label1 = self.build_label() + labelerror = self.build_label() + labelend = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(vhalt, label1)) + self.register_instruction(cil.CILGotoNode(labelerror)) + + self.register_instruction(label1) + + v_type = self.define_internal_local() + self.register_instruction(cil.CILTypeOfNode(v_type, v_box_eval)) + + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(v_box_eval)) + for p in params: + self.register_instruction(cil.CILParamNode(p)) + + self.register_instruction(cil.CILDynamicCallNode(dest, v_type, method_.vmholder)) + self.register_instruction(cil.CILGotoNode(labelend)) + + self.register_instruction(labelerror) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_1'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(labelend) + else: + params = [] + method_ = self.dottypes[node.typeName].methods[node.function].finfo + + for i, expr in enumerate(node.args): + vlocal = self.define_internal_local() + self.visit(expr, vlocal) + p = method_.paramsType[i] + + v_box = self._ifobjectboxing(vlocal, expr.typeName, p) + params.append(v_box) + + v_expr = self.define_internal_local() + self.visit(node.instance, v_expr) + + v_box_eval = self._ifboxing(v_expr, node.instance.typeName) + + vhalt = self.define_internal_local() + self.register_instruction(cil.CILMinusNode(vhalt, self.void, v_box_eval)) + + label1 = self.build_label() + labelerror = self.build_label() + labelend = self.build_label() + + self.register_instruction(cil.CILGotoIfNode(vhalt, label1)) + self.register_instruction(cil.CILGotoNode(labelerror)) + + self.register_instruction(label1) + + self.register_instruction(cil.CILSaveState()) + self.register_instruction(cil.CILParamNode(v_box_eval)) + + for p in params: + self.register_instruction(cil.CILParamNode(p)) + + self.register_instruction(cil.CILStaticCallNode(dest, method_.name)) + self.register_instruction(cil.CILGotoNode(labelend)) + + self.register_instruction(labelerror) + var1 = self.define_internal_local() + self.register_instruction(cil.CILLoadNode(var1, self.dotdata['exception_1'])) + self.register_instruction(cil.CILPrintStrNode(var1)) + self.register_instruction(cil.CILErrorNode()) + + self.register_instruction(labelend) + + # @visitor.when(ast.Void) + # def visit(self, node: ast.Void, dest): + # # print("------------visit node: Void") + # self.register_instruction(cil.CILAssignNode(dest, self.void)) + + # ====================================================================== + + def _find(self, name): + for argument in self.arguments: + if argument.vinfo.name == name: + return argument.vinfo + + for cilLocalNode in self.localvars: + if cilLocalNode.vinfo.name == name: + return cilLocalNode.vinfo + + dest = self.define_internal_local() + vself = self._find('self') + # vtype = self.define_internal_local() + # self.register_instruction(cil.CILTypeOfNode(vtype, vself)) + num = self.dottypes[self.current_class.cinfo.name].attrs[name].vmholder + self.register_instruction(cil.CILGetAttribNode(dest, vself, num)) + return dest \ No newline at end of file diff --git a/src/coolc.sh b/src/coolc.sh index 3088de4f..e094bd1b 100755 --- a/src/coolc.sh +++ b/src/coolc.sh @@ -4,8 +4,8 @@ INPUT_FILE=$1 OUTPUT_FILE=${INPUT_FILE:0: -2}mips # Si su compilador no lo hace ya, aquí puede imprimir la información de contacto -echo "LINEA_CON_NOMBRE_Y_VERSION_DEL_COMPILADOR" # TODO: Recuerde cambiar estas -echo "Copyright (c) 2019: Nombre1, Nombre2, Nombre3" # TODO: líneas a los valores correctos +echo "cool ytejeda03 v0.1" +echo "Copyright (c) 2019: Yunior Alexander Tejeda Illana, Gabriela Mijenes" # Llamar al compilador echo "Compiling $INPUT_FILE into $OUTPUT_FILE" diff --git a/src/lexer.py b/src/lexer.py new file mode 100644 index 00000000..2860a283 --- /dev/null +++ b/src/lexer.py @@ -0,0 +1,421 @@ +from ply import lex + +errors = [] +reserved = { + 'class': 'CLASS', + 'else': 'ELSE', + 'false': 'FALSE', + 'fi': 'FI', + 'if': 'IF', + 'inherits': 'INHERITS', + 'in': 'IN', + 'isvoid': 'ISVOID', + 'let': 'LET', + 'loop': 'LOOP', + 'pool': 'POOL', + 'then': 'THEN', + 'while': 'WHILE', + 'case': 'CASE', + 'esac': 'ESAC', + 'new': 'NEW', + 'of': 'OF', + 'not': 'NOT', + 'true': 'TRUE', +} + +tokens = [ + 'NUMBER', + 'STRING', + 'PLUS', + 'MINUS', + 'TIMES', + 'DIVIDE', + 'LPAREN', + 'RPAREN', + 'ATTRIBUTEID', + 'CLASSID', + 'LBRACE', + 'RBRACE', + 'COMMA', + 'SEMICOLON', + 'COLON', + 'ASSIGNATION', + 'ARROW', + 'DOT', + 'LESS', + 'LESSEQUAL', + 'GREATER', + 'GREATEREQUAL', + 'EQUAL', + 'COMPLEMENT', + 'DISPATCH' + ] + list(reserved.values()) + +t_ignore = ' \t\r\v\f' + +def t_INLINECOMMENT(token): + r'--.*' + pass + +def t_start_comment(token): + r'\(\*' + token.lexer.push_state("COMMENT") + token.lexer.counter = 1 + token.lexer.star = False + token.lexer.lparen = False + +def t_start_string(token): + r'"' + token.lexer.push_state("STRING") + token.lexer.string_backslashed = False + token.lexer.stringbuf = "" + token.lexer.string_containsNull = False + token.lexer.string_nullrow = 0 + token.lexer.string_nullcol = 0 + +def t_PLUS(token): + r'\+' + token.value = '+' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_MINUS(token): + r'-' + token.value = '-' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_TIMES(token): + r'\*' + token.value = '*' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_DIVIDE(token): + r'/' + token.value = '/' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_LPAREN(token): + r'\(' + token.value = '(' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_RPAREN(t): + r'\)' + t.value = ')' + t.colno = find_column(t.lexer.lexdata, t) + return t + +def t_LBRACE(token): + r'\{' + token.value = '{' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_RBRACE(token): + r'\}' + token.value = '}' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_COMMA(token): + r',' + token.value = ',' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_SEMICOLON(token): + r';' + token.value = ';' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_COLON(token): + r':' + token.value = ':' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_ASSIGNATION(token): + r'<-' + token.value = '<-' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_ARROW(token): + r'=>' + token.value = '=>' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_DOT(token): + r'\.' + token.value = '.' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_LESSEQUAL(token): + r'<=' + token.value = '<=' + token.colno = find_column(token.lexer.lexdata, token) + return token + + +def t_LESS(token): + r'<' + token.value = '<' + token.colno = find_column(token.lexer.lexdata, token) + return token + + +def t_GREATEREQUAL(token): + r'>=' + token.value = '>=' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_GREATER(token): + r'>' + token.value = '>' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_EQUAL(token): + r'=' + token.value = '=' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_COMPLEMENT(token): + r'~' + token.value = '~' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_DISPATCH(token): + r'@' + token.value = '@' + token.colno = find_column(token.lexer.lexdata, token) + return token + +def t_NUMBER(token): + r'\d+' + token.value = int(token.value) + token.colno = find_column(token.lexer.lexdata, token) + return token + + +states = ( + ('STRING', 'exclusive'), + ('COMMENT', 'exclusive'), +) + + +def t_STRING_newline(token): + r'\n' + global errors + token.lexer.lineno += 1 + if not token.lexer.string_backslashed: + errors.append( + "(%s, %s) - LexicographicError: Unterminated string constant" % (token.lineno, find_column(token.lexer.lexdata, token))) + token.lexer.pop_state() + else: + token.lexer.string_backslashed = False + + +def t_COMMENT_eof(token): + r'\$' + global errors + s = token.lexer.lexdata + lineCount = s.count('\n') + 1 + posCount = 1 + i = len(s) - 1 + while i >= 0 and s[i] != '\n': + posCount += 1 + i -= 1 + errors.append("(%s, %s) - LexicographicError: EOF in comment" % (lineCount, find_column(token.lexer.lexdata, token) - 1)) + + +def t_COMMENT_star(token): + r'\*' + if (token.lexer.lparen): + token.lexer.lparen = False + token.lexer.counter += 1 + else: + token.lexer.star = True + + +def t_COMMENT_lparen(token): + r'\(' + token.lexerlparen = True + if (token.lexer.star): + token.lexer.start = False + + +def t_STRING_eof(token): + r'\$' + global errors + errors.append("(%s, %s) - LexicographicError: EOF in string constant" % + (token.lineno, find_column(token.lexer.lexdata, token) - 1)) + token.lexer.pop_state() + + +def t_COMMENT_rparen(token): + r'\)' + if token.lexer.star: + token.lexer.star = False + token.lexer.counter -= 1 + if token.lexer.counter == 0: + token.lexer.pop_state() + + +def t_STRING_end(token): + r'"' + global errors + if not token.lexer.string_backslashed: + token.lexer.pop_state() + if token.lexer.string_containsNull: + errors.append("(%s, %s) - LexicographicError: String contains null character" % ( + token.lexer.string_nullrow, token.lexer.string_nullcol)) + token.lexer.skip(1) + else: + token.value = token.lexer.stringbuf + token.type = "STRING" + token.colno = find_column(token.lexer.lexdata, token) + return token + else: + token.lexer.stringbuf += '"' + token.lexer.string_backslashed = False + + +def t_COMMENT_anything(token): + r'(.|\n)' + pass + + +def t_STRING_anything(token): + r'[^\n]' + if token.lexer.string_backslashed: + if token.value == 'b': + token.lexer.stringbuf += '\b' + elif token.value == 't': + token.lexer.stringbuf += '\t' + elif token.value == 'n': + token.lexer.stringbuf += '\n' + elif token.value == 'f': + token.lexer.stringbuf += '\f' + elif token.value == '\\': + token.lexer.stringbuf += '\\' + elif token.value == '0': + t_STRING_error(token) + else: + token.lexer.stringbuf += token.value + token.lexer.string_backslashed = False + else: + if token.value != '\\': + token.lexer.stringbuf += token.value + else: + token.lexer.string_backslashed = True + + +t_STRING_ignore = '' + + +def t_STRING_error(token): + token.lexer.string_containsNull = True + token.lexer.string_nullrow = token.lineno + token.lexer.string_nullcol = find_column(token.lexer.lexdata, token) - 1 + + +t_COMMENT_ignore = '' + + +def t_COMMENT_error(token): + token.lexer.counter = 0 + token.lexer.star = False + token.lexer.lparen = False + + +def t_newline(token): + r'\n+' + token.lexer.lineno += len(token.value) + + +def t_ATTRIBUTEID(token): + r'[a-z][a-zA-Z_0-9]*' + if reserved.get(token.value.lower()) is None: + token.type = 'ATTRIBUTEID' + else: + token.type = reserved.get(token.value.lower()) + token.colno = find_column(token.lexer.lexdata, token) + return token + + +def t_CLASSID(token): + r'[A-Z][a-zA-Z_0-9]*' + if reserved.get(token.value.lower()) is None or reserved.get(token.value.lower()) == 'TRUE' or reserved.get( + token.value.lower()) == 'FALSE': + token.type = 'CLASSID' + else: + token.type = reserved.get(token.value.lower()) + token.colno = find_column(token.lexer.lexdata, token) + return token + + +def find_column(input, token): + line_start = input.rfind('\n', 0, token.lexpos) + 1 + return (token.lexpos - line_start) + 1 + + +def t_error(token): + global errors + if not (token.value[0] == '$' and token.lexpos + 1 == len(token.lexer.lexdata)): + errors.append('(%s, %s) - LexicographicError: ERROR "%s"' % (token.lineno, find_column(token.lexer.lexdata, token), token.value[0])) + token.lexer.skip(1) + + +def make_lexer(data): + newData = "" + global errors + errors = [] + i = 0 + while i < len(data): + if data[i] == '(' and i < len(data) and data[i + 1] == '*': + counter = 0 + j = i + 2 + paster = "" + matched = False + while j < len(data) - 1: + if data[j] == '(' and data[j + 1] == '*': + counter += 1 + j += 1 + if data[j] == '*' and data[j + 1] == ')': + if counter == 0: + matched = True + break + else: + counter -= 1 + if data[j] == '\n': + paster += '\n' + j += 1 + if matched: + newData += paster + i = j + 2 + continue + newData += data[i] + i += 1 + + newData = newData + '$' + lexer.input(newData) + while True: + tok = lexer.token() + if not tok: + break + lexer.lineno = 1 + return lexer, errors + + +lexer = lex.lex() diff --git a/src/mips.py b/src/mips.py new file mode 100644 index 00000000..7728b8d6 --- /dev/null +++ b/src/mips.py @@ -0,0 +1,395 @@ +import visitor +import cil_hierarchy as cil +# from context import Hierarchy +import context +import mips_utility as util +# from hierarchy import TypeHierarchy as Hierarchy + +import context as ctx +instruction = "" +enter = "\n" + +class VisitorMIPS: + def __init__(self): + self.internal_count = 0 + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(cil.CILProgramNode) + def visit(self, node): + data = ".data " + enter + textinit = (".globl main" + enter + + ".text " + enter) + labels = "" + text = "main:" + enter + + for item in node.dottypes.values(): + data += self.visit(item) + + + for item in node.dotdata.values(): + data += self.visit(item) + + for item in node.dotcode: + labels += self.visit(item) + + data += "buffer: .space 1024" + enter + text += "j entry" + enter + + + return data + textinit + text + labels + + @visitor.when(cil.CILDataNode) + def visit(self, node): + + return "" + node.vname + ": .asciiz " + "\""+ node.value + "\""+ enter + + @visitor.when(cil.CILTypeNode) + def visit(self, node): + labelbody = "" + + data = (node.cinfo.name + ": " + + ".word " + str(node.cinfo.meth_length + 8) + enter) + + parent = node.cinfo.parent + if parent == None: + data += ".word 0" + enter + else: + data += ".word " + parent.cinfo.name + enter + + + lista = list(node.methods.values()) + lista.sort(key=lambda x:x.finfo.vmholder) + + for func in lista: + data += ".word " + func.finfo.name + enter + data += ".asciiz " + "\""+ node.cinfo.name + "\""+ enter + + return data + + @visitor.when(cil.CILFunctionNode) + def visit(self, node): + label = "" + node.finfo.name + + text = ("# cil function Node" + enter + + label +":"+ enter) + pos_sp = len(node.arguments) * 4 + + text += "addi $a3, $sp, " + str(pos_sp)+ enter + + text += ("# reservar locarvars" + enter + + util.ReservaPila(len(node.localvars))) + + for item in node.instructions: + text += self.visit(item) + + return text + + @visitor.when(cil.CILAssignNode) + def visit(self, node): + # print("----------->CILAssignNode") + text = "# assign" + enter + if isinstance(node.source,int): + text += "li $t1, " + str(node.source) + enter + else: + text += "lw $t1, " + "-"+ str(4*node.source.vmholder)+"($a3)" + enter + + text += "sw $t1, " + "-"+ str(4*node.dest.vmholder)+"($a3)" + enter + return text + + @visitor.when(cil.CILPlusNode) + def visit(self, node): + text = "# CILPlusNode" + enter + + text += util.Opera("add",node) + return text + + @visitor.when(cil.CILMinusNode) + def visit(self, node): + # print("----------->CILMinusNode") + text = "# CILMinusNode" + enter + # text += util.Opera("sub",4*(node.dest.vmholder),4*(node.left.vmholder),4*(node.right.vmholder)) + text += util.Opera("sub",node) + return text + + @visitor.when(cil.CILStarNode) # necesito en el vinfo q haya un flag q m diga si es int o no + def visit(self, node): + # print("----------->CILStarNode") + text = "# CILStarNode" + enter + # text += util.OperaSpecial("mult",4*(node.dest.vmholder),4*(node.left.vmholder),4*(node.right.vmholder)) + text += util.Opera("mul",node) + return text + + @visitor.when(cil.CILDivNode) # necesito en el vinfo q haya un flag q m diga si es int o no + def visit(self, node): + # print("----------->CILDivNode") + text = "# CILDivNode" + enter + # text += util.OperaSpecial("div",4*(node.dest.vmholder),4*(node.left.vmholder),4*(node.right.vmholder)) + text += util.OperaSpecial("div",node) + return text + + @visitor.when(cil.CILAllocateNode) + def visit(self, node): + # print("----------->CILAllocateNode") + text = "# CILAllocateNode" + enter + tam = node.cinfo.attr_length + text += (util.ReservaMemoria(tam+4) + + " # guardar en dest" + enter + + "sw $v0, "+ "-"+ str(4*(node.dest.vmholder))+"($a3)" + enter + + " # en la instancia poner referencia a su info_table" + enter + + "la $t1, "+ node.cinfo.name + enter + + "sw $t1, 0($v0)" + enter) + return text + + @visitor.when(cil.CILGotoIfNode) + def visit(self, node): + # print("----------->CILGotoIfNode") + text = "# CILGotoIfNode" + enter + text += ( "lw $t1, " + "-"+ str(4*(node.vinfo.vmholder))+"($a3)"+ enter + +"bne $t1, $zero, "+ node.label.name + enter) + return text + + @visitor.when(cil.CILGotoNode) + def visit(self, node): + # print("----------->CILGotoNode") + text = "# CILGotoNode" + enter + text += "j "+ node.label.name + enter + return text + + @visitor.when(cil.CILLabelNode) + def visit(self, node): + # print("----------->CILLabelNode") + text = "# CILLabelNode" + enter + text += node.name +":" + enter + return text + + @visitor.when(cil.CILTypeOfNode) + def visit(self, node): + # print("----------->CILTypeOfNode") + text = "# CILTypeOfNode" + enter + text += ("# llegar hasta la inf_table" + enter + + "lw $t1, " + "-"+ str(4*(node.var.vmholder))+"($a3)"+ enter + + "lw $t2, 0($t1) " + enter + # + "lw $v1, 0($t2)"+ enter + + "# guardarlo en destino" + enter + + "sw $t2," + "-"+ str(4*(node.dest.vmholder))+"($a3)"+ enter) + return text + + @visitor.when(cil.CILLoadNode) + def visit(self, node): + # print("----------->CILLoadNode") + text = "# CILLoadNode" + enter + text += ("la $t1, " + node.msg.vname + enter + + "sw $t1," + "-"+ str(4*node.dest.vmholder)+"($a3)"+ enter ) + return text + + @visitor.when(cil.CILParamNode) + def visit(self, node): + # print("----------->CILParamNode") + text = "# CILParamNode " + enter + text += "lw $t1, "+ "-"+ str(4*node.vinfo.vmholder)+"($a3)" + enter + text += util.Push("$t1") + return text + + @visitor.when(cil.CILSetAttribNode) + def visit(self, node): + # print("----------->CILSetAttribNode") + text = "# CILSetAttribNode" + enter + text += ("lw $t1, "+ "-"+ str(4*node.dest.vmholder)+"($a3)" + enter + +"addi $t2, $t1, "+ str(4*node.nattr)+ enter + +"lw $t3, "+ "-"+ str(4*node.source.vmholder)+"($a3)" + enter + + "sw $t3, 0($t2)"+ enter) + return text + + @visitor.when(cil.CILGetAttribNode) + def visit(self, node): + # print("----------->CILGetAttribNode") + text = "# CILGetAttribNode" + enter + text += ("lw $t1, "+ "-"+ str(4*node.source.vmholder)+"($a3)" + enter + +"lw $t2, "+ str(4*node.nattr)+ "($t1)" + enter + +"addi $t3, $a3, "+ "-"+ str(4*node.dest.vmholder)+ enter + + "sw $t2, 0($t3)"+ enter) + return text + + @visitor.when(cil.CILGetIndexNode) + def visit(self, node): + # print("----------->CILGetIndexNode") + text = "# CILGetIndexNode" + enter + text += ("lw $t1, "+ "-"+ str(4*node.array.vmholder)+"($a3)" + enter + + "lw $t2, -"+ str(4*node.index.vmholder)+"($a3)" + enter + + "add $t3, $t1,$t2" + enter + + "lb $t4, 0($t3) " + enter + + "li $t2, 0" + enter + + "sw $t2, " + "-"+ str(4*node.dest.vmholder)+"($a3)" + enter + + "sb $t4, " + "-"+ str(4*node.dest.vmholder)+"($a3)" + enter) + return text + + @visitor.when(cil.CILReturnNode) + def visit(self, node): + # print("----------->CILReturnNode") + text = "# CILReturnNode" + enter + if node.value == None: + text += "li $v1, 0" + enter + # text += "jr $ra" + # return text + elif isinstance(node.value,int): + text += "li $v1, " + str(node.value) + enter + # text += "jr $ra" + else: + text += ("lw $t1, "+ "-"+ str(4*node.value.vmholder)+"($a3)" + enter + + "move $v1, $t1" + enter ) + text += "# restaurar pila con respecto al metodo" + enter + text += "move $sp, $a3" + enter + text += "jr $ra"+ enter + return text + + @visitor.when(cil.CILSaveState) + def visit(self, node): + # print("----------->CILSaveState") + text = (" # SaveState"+ enter + + util.SalvaRegistros()) + return text + + @visitor.when(cil.CILStaticCallNode) + def visit(self, node): + # print("----------->CILStaticCallNode") + text = (" # CILStaticCallNode" + enter + + "jal " + node.meth_name + enter + + util.CargaRegistros() + + "sw $v1, -" + str(4*node.dest.vmholder) +"($a3)" + enter) + + + return text + + @visitor.when(cil.CILDynamicCallNode) + def visit(self, node): + # print("----------->CILDynamicCallNode") + text = "# CILDynamicCallNode" + enter + text+= ("lw $t1, -" + str(4*node.ctype.vmholder)+"($a3)"+ enter + + "lw $t2, "+ str(4*node.meth_name)+"($t1)"+ enter + + "jalr $t2" + enter + + util.CargaRegistros() + + "sw $v1, -" + str(4*node.dest.vmholder) +"($a3)" + enter) + return text + + + + + @visitor.when(cil.CILLengthNode) + def visit(self, node): + # print("----------->CILLengthNode") + text = (util.Length(node.array.vmholder,self) + + "sw $s0, "+ "-"+ str(4*node.dest.vmholder)+"($a3)" + enter) + return text + + + @visitor.when(cil.CILConcatNode) + def visit(self, node): + # print("----------->CILConcatNode") + text = "# CILConcatNode" + enter + text += util.Concat(4*node.array1.vmholder,4*node.array2.vmholder,self) + text += "sw $t5, -"+ str(4*node.dest.vmholder) +"($a3)" + enter + return text + + + + @visitor.when(cil.CILSubstringNode) + def visit(self, node): + # print("----------->CILSubstringNode") + text = ("# CILSubstringNode" + enter + + util.Substring(4*node.i.vmholder,4*node.l.vmholder,4*node.array.vmholder,self) + + "sw $v0, "+ "-"+ str(4*node.dest.vmholder)+"($a3)"+ enter) + return text + + + + @visitor.when(cil.CILReadStrNode) + def visit(self, node): + # print("----------->CILReadStrNode") + text = ("# CILReadStrNode" + enter + + util.leerString(self) + + "sw $t5, -" + str(4*node.vinfo.vmholder)+"($a3)" + enter) + return text + + + + @visitor.when(cil.CILReadIntNode) + def visit(self, node): + # print("----------->CILReadIntNode") + text = ("# CILReadNodeInt" + enter + + "li $v0, 5" + enter + + "syscall"+ enter + + "sw $v0, " + util.DeLaPila(node.vinfo.vmholder)) + return text + + + @visitor.when(cil.CILPrintIntNode) + def visit(self, node): + # print("----------->CILPrintIntNode") + text = (" # CILPrintNodeInt " + enter + + "lw $t1, " + util.DeLaPila(node.vinfo.vmholder) + + "li $v0, 1" + enter + + "move $a0, $t1" + enter + + "syscall"+ enter) + return text + + @visitor.when(cil.CILPrintStrNode) + def visit(self, node): + # print("----------->CILPrintStrNode") + text = (" # CILPrintNodeStr " + enter + + "lw $t1, " + util.DeLaPila(node.vinfo.vmholder) + + "li $v0, 4" + enter + + "move $a0, $t1" + enter + + "syscall"+ enter) + return text + + @visitor.when(cil.CILParentNode) + def visit(self, node): + # print("----------->CILParentNode") + text = " # CILParentNode" + enter + text += "lw $t1, -" + str(4*node.ntype.vmholder) + "($a3)" + enter + text += "lw $t2, 4($t1) " + enter + text += "sw $t2, -"+ str(4*node.dest.vmholder) + "($a3)" + enter + return text + + @visitor.when(cil.CILErrorNode) + def visit(self, node): + # print("----------->CILErrorNode") + text = "# CILErrorNode" + enter + text += "li $a0, "+ str(node.num) + enter + text += "li $v0, 17" + enter + text += "syscall" + enter + return text + + @visitor.when(cil.CILLessThan) + def visit(self, node): + # print("----------->CILLessThan") + text = ("# CILLessThan" + enter + + "lw $t1, -" + str(4*node.left.vmholder) +"($a3)" + enter + + "lw $t2, -" + str(4*node.right.vmholder) +"($a3)" + enter + + "slt $t3, $t1, $t2" + enter + + "sw $t3, -" + str(4*node.dest.vmholder)+"($a3)" + enter) + return text + + @visitor.when(cil.CILTypeName) + def visit(self, node): + # print("----------->CILTypeName") + text = ("# CILTypeName" + enter + + "lw $t1, -" + str(4*node.nclass.vmholder) +"($a3)" + enter + + "lw $t2, 0($t1)" + enter + + "add $t3, $t2, $t1" + enter + # + "lw $t4, 0($t3)" + enter + + "sw $t3, -" + str(4*node.dest.vmholder)+"($a3)" + enter) + return text + + @visitor.when(cil.CILReturnFinal) + def visit(self, node): + # print("----------->CILReturnFinal") + text = "# CILReturnFinal" + enter + text += "li $a0, 0" + enter + text += "li $v0, 17" + enter + text += "syscall" + enter + return text + \ No newline at end of file diff --git a/src/mips_utility.py b/src/mips_utility.py new file mode 100644 index 00000000..3127d92d --- /dev/null +++ b/src/mips_utility.py @@ -0,0 +1,375 @@ +enter = "\n" + +def build_label(label,visitor): + fname = '{}_{}'.format(label,visitor.internal_count) + visitor.internal_count += 1 + return fname + + + +def ReservaMemoria(size): + # tam = size*4 + text =("# reserva memoria" + enter + + "li $a0, " + str(size) + enter + + "li $v0, 9" + enter + + "syscall" + enter) + return text # en v0 guarda laposicion d memoria inicial + +def PrintStr(varname): + text = ("" + "la $t1, " + varname + enter + + "move $a0, $t1" + enter + + "li $v0, 4" + enter + + "syscall" + enter) + return text + + +def AccederALabel(className ,fpos): + calcpos = (fpos * 4) + 8 + text = ("" + "la $t1, " + className + str(calcpos) + enter) + return text + +def SalvaRegistros(): + text = ("# Salva registros" + enter + + "addi $sp, $sp, -76" + enter + + "sw $t1, 0($sp)" + enter + + "sw $t2, 4($sp)" + enter + + "sw $t3, 8($sp)" + enter + + "sw $t4, 12($sp)" + enter + + "sw $t5, 16($sp)" + enter + + "sw $t6, 20($sp)" + enter + + "sw $t7, 24($sp)" + enter + + "sw $a0, 28($sp)" + enter + + "sw $a1, 32($sp)" + enter + + "sw $a2, 36($sp)" + enter + + "sw $a3, 40($sp)" + enter + + "sw $ra, 44($sp)" + enter + + "sw $s1, 48($sp)" + enter + + "sw $s2, 52($sp)" + enter + + "sw $s3, 56($sp)" + enter + + "sw $s4, 60($sp)" + enter + + "sw $s5, 64($sp)" + enter + + "sw $s6, 68($sp)" + enter + + "sw $s7, 72($sp)" + enter + + ) + return text + +def CargaRegistros(): + text = ("# Carga registros" + enter + + "lw $t1, 0($sp)" + enter + + "lw $t2, 4($sp)" + enter + + "lw $t3, 8($sp)" + enter + + "lw $t4, 12($sp)" + enter + + "lw $t5, 16($sp)" + enter + + "lw $t6, 20($sp)" + enter + + "lw $t7, 24($sp)" + enter + + "lw $a0, 28($sp)" + enter + + "lw $a1, 32($sp)" + enter + + "lw $a2, 36($sp)" + enter + + "lw $a3, 40($sp)" + enter + + "lw $ra, 44($sp)" + enter + + "lw $s1, 48($sp)" + enter + + "lw $s2, 52($sp)" + enter + + "lw $s3, 56($sp)" + enter + + "lw $s4, 60($sp)" + enter + + "lw $s5, 64($sp)" + enter + + "lw $s6, 68($sp)" + enter + + "lw $s7, 72($sp)" + enter + + "addi $sp, $sp, 76" + enter + ) + return text + +# def CalcPosicPila(distacia): +# return distacia*4 + + +def Opera(op,node): + text = "" + if(isinstance(node.left,int)): + text += "li $t2, " +str(node.left) + enter + else: + text += "lw $t2, " + "-" + str(4*(node.left.vmholder))+"($a3)" + enter + if(isinstance(node.right,int)): + text += "li $t3, " +str(node.right) + enter + else: + text += "lw $t3, " + "-" + str(4*(node.right.vmholder))+"($a3)" + enter + text += (op + " $t1, $t2, $t3" + enter + + "sw $t1, " + "-" + str(4*(node.dest.vmholder))+"($a3)" + enter) + + + + # text = ("lw $t1, " + str(dest)+"($a3)" + enter + # text = ( "lw $t2, " + "-" + str(left)+"($a3)" + enter + # +"lw $t3, " + "-" + str(right)+"($a3)" + enter + # + op + " $t1, $t2, $t3" + enter + # + "sw $t1, " + "-" + str(dest)+"($a3)" + enter) + return text + +def OperaSpecial(op,node): + # text = ("lw $t1, " + str(dest)+"($a3)" + enter + text = "" + if(isinstance(node.left,int)): + text += "li $t2, " +str(node.left) + enter + else: + text += "lw $t2, " + "-" + str(4*(node.left.vmholder))+"($a3)" + enter + if(isinstance(node.right,int)): + text += "li $t3, " +str(node.right) + enter + else: + text += "lw $t3, " + "-" + str(4*(node.right.vmholder))+"($a3)" + enter + + text += ( op + " $t2, $t3" + enter + + "mflo $t1, " + enter + + "sw $t1, " + "-" + str(4* node.dest.vmholder)+"($a3)" + enter) + + # text = ( "lw $t2, " + "-" + str(left)+"($a3)" + enter + # + "lw $t3, " + "-" + str(right)+"($a3)" + enter + # + op + " $t2, $t3" + enter + # + "mfhi $t1, " + enter + # + "sw $t1, " + "-" + str(dest)+"($a3)" + enter) + return text + +def DeLaPila(pos): + return "-" + str(4*pos)+"($a3)" + enter + +def Push(reg): + text = ("# push" + enter + + "addi $sp, $sp, -4" + enter + + "sw " +reg+", 0($sp)" + enter) + return text + +def Pop(reg): + text = ("# pop" + enter + + "sw " +reg+", 0($sp)" + enter + + "addi $sp, $sp, 4" + enter ) + return text + +def ReservaPila(size): + tam = size * 4 + text = "add $sp, $sp, -" + str(tam) + enter + return text + + +def Length(name,visitor): + while1 = build_label("while",visitor) + fin = build_label("fin",visitor) + text = (" # Length" + enter + + "li $s0, 0" + enter + + while1 + ":" + enter + + "lw $t0, -" + str(4*name)+ "($a3)" + enter + + "add $t0, $t0,$s0" + enter + + "lb $t1, 0($t0)" + enter + + "beq $t1, $zero, " +fin + enter + + "addi $s0,$s0,1" + enter + + "j " + while1 + enter + + fin +":" + enter) + return text + +def Substring(i,j,pos,visitor): + # while1 = build_label("while",visitor) + # fin = build_label("fin",visitor) + # text = (" # Substring" + enter + # + "lw $s3, " +str(pos)+"($a3)" + enter + # + "addi $s3, $s3, " + str(i) + enter + # + "li $t2, " + str(n) + enter + # + "li $a0, 10" + enter + # + "li $v0, 9" + enter + # + "syscall" + enter + # + "li $s0, 0" + enter + # + while1 +":" + enter + # + "move $t4, $v0" + enter + # + "move $t0, $s3" + enter + # + "add $t0, $t0,$s0" + enter + # + "add $t4, $t4, $s0" + enter + # + "lb $t1, 0($t0)" + enter + # + "sb $t1, 0($t4)" + enter + # + "addi $s0,$s0,1" + enter + # + "beq $s0, $t2, "+ fin + enter + # + "j "+ while1 + enter + # + fin + ":" + enter + # + "addi $s0,$s0,1" + enter + # + "add $t4, $t4, $s0" + enter + # + "li $t5, 0" + enter + # + "lb $t5, 0($t4)" + enter) + # return text + + while1 = build_label("while",visitor) + fin = build_label("fin",visitor) + text = (" # Substring" + enter + + "lw $s3, -" +str(pos)+"($a3)" + enter + + "lw $t1, -" +str(i)+"($a3)" + enter + + "lw $t2, -" +str(j)+"($a3)" + enter + + "add $s3, $s3, $t1" + enter + # + "sub $t2, $t2, $t1" + enter + # + "move $t2, $t3" + enter + # + "addi $t2, $t2, 1" + enter + + + "addi $a0, $t2, 1" + enter + + "li $v0, 9" + enter + + "syscall" + enter + + "li $s0, 0" + enter + + while1 +":" + enter + + "move $t4, $v0" + enter + + "move $t0, $s3" + enter + + "add $t0, $t0,$s0" + enter + + "add $t4, $t4, $s0" + enter + + "lb $t1, 0($t0)" + enter + + "sb $t1, 0($t4)" + enter + + "addi $s0,$s0,1" + enter + + "beq $s0, $t2, "+ fin + enter + + "j "+ while1 + enter + + fin + ":" + enter + + "addi $s0,$s0,1" + enter + + "addi $t4, $t4, 1" + enter + + "li $t5, 0" + enter + + "lb $t5, 0($t4)" + enter) + return text + +def Concat(pos1, pos2,visitor): + whilel1 = build_label("whilel1",visitor) + whilel2 = build_label("whilel2",visitor) + fin = build_label("fin",visitor) + pawhilel1 = build_label("pawhilel1",visitor) + pawhilel2 = build_label("pawhilel2",visitor) + whilecopy1 = build_label("whilecopy1",visitor) + whilecopy2 = build_label("whilecopy2",visitor) + pawhilecopy2 = build_label("pawhilecopy2",visitor) + finl = build_label("finl",visitor) + text = ( "# Concat" + enter + + "lw $t1, -" + str(pos1)+"($a3)" + enter + + "li $s0, 0 " + enter + + whilel1 + ": " + enter + + + "lw $t0, -" + str(pos1)+"($a3)" + enter + + "add $t0, $t0,$s0 " + enter + + "lb $t1, 0($t0) " + enter + + "beq $t1, $zero, " + pawhilel2 + enter + + "addi $s0,$s0,1 " + enter + + "j " + whilel1 + enter + + pawhilel2 + ":" + enter + + + "move $t7,$s0 " + enter + + "li $s0, 0 " + enter + + whilel2 +": " + enter + + "lw $t0, -" + str(pos2)+"($a3)" + enter + + "add $t0, $t0,$s0 " + enter + + "lb $t1, 0($t0) " + enter + + "beq $t1, $zero, "+ finl + enter + + "addi $s0, $s0,1 " + enter + + "j " + whilel2 + enter + + finl +": " + enter + + + "add $t7, $t7,$s0 " + enter + + "addi $t7, $t7, 1 " + enter + + "move $a0,$t7 " + enter + + "li $v0, 9 " + enter + + "syscall " + enter + + "li $s0, 0 " + enter + + "li $s1, 0 " + enter + + "move $t5, $v0 " + enter + + "# puntero en t5" + enter + + whilecopy1 + ": " + enter + + + "# puntero en a" + enter + + "lw $t0, -" + str(pos1)+"($a3)" + enter + + "add $t0, $t0,$s0 " + enter + + "add $t4, $t5, $s0 " + enter + + "lb $t1, 0($t0)" + enter + + "beq $t1, $s1, " + pawhilecopy2 + enter + + "addi $s0,$s0,1 " + enter + + "# move $a0,$s0 " + enter + + "# li $v0, 1 " + enter + + "# syscall " + enter + + "sb $t1, 0($t4)" + enter + + "j " + whilecopy1 + enter + + pawhilecopy2 + ": " + enter + + + "# move $a0,$s0 " + enter + + "# li $v0, 1 " + enter + + "# syscall " + enter + + "move $t7, $s0" + enter + + "li $s0, 0 " + enter + + whilecopy2 +":" + enter + + + "# puntero en a2" + enter + + "lw $t0, -" + str(pos2)+"($a3)" + enter + + "add $t0, $t0,$s0 " + enter + + "add $t4, $t5, $t7 " + enter + + "lb $t1, 0($t0) " + enter + + "sb $t1, 0($t4) " + enter + + "beq $t1, $zero, "+ fin + enter + + "addi $s0,$s0,1 " + enter + + "addi $t7,$t7,1 " + enter + + "j " + whilecopy2 + enter + + fin +": " + enter + + + "add $t4, $t5, $t7 " + enter + + "li $t1, 0 " + enter + + "lb $t1, 0($t4)" + enter + + "# li $v0, 4" + enter + + "# move $a0, $t5" + enter + + "# syscall" + enter) + return text + + +def leerString(visitor): + while1 = build_label("while1",visitor) + while2 = build_label("while2",visitor) + fin = build_label("fin",visitor) + fin1 = build_label("fin1",visitor) + + text = (" # leer string" + enter + + "li $s0,0 " + enter + + "li $s3, 10 " + enter + + "# coger tamanho y almacenar en buffer " + enter + + while1 + ": " + enter + + + "la $t0, buffer " + enter + + "add $t0, $t0, $s0 " + enter + + "li $v0, 12 " + enter + + "syscall " + enter + + "addi $s0,$s0,1 " + enter + + "beq $v0, $s3, " + fin + enter + + + "# beq $v0, $zero, error " + enter + + "# error " + enter + + "sb $v0, 0($t0) " + enter + + "j " + while1 + enter + + + fin + ": " + enter + + + "li $v0, 0 " + enter + + "sb $v0, 0($t0) " + enter + + "# reservar espacio " + enter + + "move $a0, $s0 " + enter + + "li $v0, 9 " + enter + + "syscall " + enter + + "# asignar espacio a t5 " + enter + + "move $t5, $v0 " + enter + + "li $s0,0 " + enter + + "li $s1,0 " + enter + + "li $s2,0 " + enter + + "# copiar de buffer pa t5 " + enter + + while2 + ": " + enter + + + "la $t0, buffer " + enter + + "move $t1, $t5 " + enter + + "add $t0, $t0, $s0 " + enter + + "add $t1, $t1, $s1 " + enter + + "lb $t2, 0($t0) " + enter + + "sb $t2, 0($t1) " + enter + + "beq $t2, $s2, " + fin1 + enter + + + "addi $s0,$s0,1 " + enter + + "addi $s1,$s1,1 " + enter + + + "j " + while2 + enter + + + fin1 + ": " + enter ) + return text + + +# q usaste ply +# visitor y q hacen, q erores +# a;adir cosas a cil y q cosas usate +# dond se hizo case, representacion d tipos rn memoria, vt , boximh unboxing +# trabajo con la pila \ No newline at end of file diff --git a/src/my_parser.py b/src/my_parser.py new file mode 100644 index 00000000..13dda20e --- /dev/null +++ b/src/my_parser.py @@ -0,0 +1,306 @@ +import ply.yacc as yacc +from lexer import tokens +from ast_hierarchy import * + +start = 'program' + +errors = [] + +def findCol(p, lexPos): + lineStart = p.lexer.lexdata.rfind('\n', 0, lexPos) + 1 + return (lexPos - lineStart) + 1 + +def GetPos(p, x): + return p.lineno(x), findCol(p, p.lexpos(x)) + +def p_program(p): + '''program : classList''' + p[0] = ProgramNode(p[1], GetPos(p, 1)) + +def p_classList(p): + '''classList : classDefinition classList + | classDefinition''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = [p[1]] + p[2] + +def p_classDefinition(p): + '''classDefinition : CLASS CLASSID LBRACE classFeatureList RBRACE SEMICOLON + | CLASS CLASSID INHERITS CLASSID LBRACE classFeatureList RBRACE SEMICOLON''' + if len(p) == 7: + p[0] = ClassNode(p[2], p[4], None, [GetPos(p, 2)]) + else: + p[0] = ClassNode(p[2], p[6], p[4], [GetPos(p, 4)]) + +def p_empty(p): + 'empty :' + pass + +def p_classFeatureList(p): + '''classFeatureList : feature classFeatureList + | empty''' + + if len(p) == 3: + p[0] = [p[1]] + p[2] + else: + p[0] = [] + +def p_feature(p): + '''feature : attributeFeature + | functionFeature''' + p[0] = p[1] + +def p_attributeFeature(p): + '''attributeFeature : ATTRIBUTEID COLON CLASSID SEMICOLON + | ATTRIBUTEID COLON CLASSID ASSIGNATION expression SEMICOLON''' + if len(p) == 5: + p[0] = AttributeFeatureNode(p[1], p[3], None, [GetPos(p, 1)]) + else: + p[0] = AttributeFeatureNode(p[1], p[3], p[5], [GetPos(p, 1)]) + +def p_functionFeature(p): + '''functionFeature : ATTRIBUTEID LPAREN parameterList RPAREN COLON CLASSID LBRACE expression RBRACE SEMICOLON + | ATTRIBUTEID LPAREN RPAREN COLON CLASSID LBRACE expression RBRACE SEMICOLON''' + if len(p) == 10: + p[0] = FunctionFeatureNode(p[1], [], p[5], p[7], [GetPos(p, 1)]) + else: + p[0] = FunctionFeatureNode(p[1], p[3], p[6], p[8], [GetPos(p, 1)]) + +def p_parameterList(p): + '''parameterList : parameter COMMA parameterList + | parameter''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = [p[1]] + p[3] + +def p_parameter(p): + '''parameter : ATTRIBUTEID COLON CLASSID''' + p[0] = ParameterNode(p[1], p[3], [GetPos(p, 3)]) + +def p_expression(p): + '''expression : notForm + | mixedExpression''' + p[0] = p[1] + +def p_notForm(p): + '''notForm : NOT mixedExpression''' + if len(p) == 2: + p[0] = p[1] + else: + p[0] = NotNode(p[2], [GetPos(p, 1)]) + +def p_mixedExpression(p): + '''mixedExpression : mixedExpression LESSEQUAL arithmeticExpression + | mixedExpression LESS arithmeticExpression + | mixedExpression EQUAL expression + | arithmeticExpression''' + if len(p) > 2: + if p[2] == "<": + p[0] = LessNode(p[1], p[3], [GetPos(p, 2)]) + else: + if p[2] == "=": + p[0] = EqualNode(p[1], p[3], [GetPos(p, 2)]) + else: + p[0] = LessEqualNode(p[1], p[3], [GetPos(p, 2)]) + else: + p[0] = p[1] + +def p_arithmeticExpression(p): + '''arithmeticExpression : arithmeticExpression PLUS term + | arithmeticExpression MINUS term + | term''' + if len(p) == 2: + p[0] = p[1] + else: + if p[2] == "+": + p[0] = PlusNode(p[1], p[3], [GetPos(p, 2)]) + else: + p[0] = MinusNode(p[1], p[3], [GetPos(p, 2)]) + +def p_term(p): + '''term : term TIMES isvoidForm + | term DIVIDE isvoidForm + | isvoidForm''' + if len(p) == 2: + p[0] = p[1] + else: + if p[2] == "*": + p[0] = TimesNode(p[1], p[3], [GetPos(p, 2)]) + else: + p[0] = DivideNode(p[1], p[3], [GetPos(p, 2)]) + +def p_isvoidForm(p): + '''isvoidForm : ISVOID expression + | complementForm''' + if len(p) == 2: + p[0] = p[1] + else: + p[0] = IsVoidNode(p[2], [GetPos(p, 1)]) + +def p_complementForm(p): + '''complementForm : COMPLEMENT expression + | programAtom''' + if len(p) == 2: + p[0] = p[1] + else: + p[0] = ComplementNode(p[2], [GetPos(p, 1)]) + +def p_programAtomBoolean(p): + '''programAtom : TRUE + | FALSE''' + p[0] = ConstantBoolNode(p[1], [GetPos(p, 1)]) + +def p_programAtomString(p): + '''programAtom : STRING''' + p[0] = ConstantStringNode(p[1], [GetPos(p, 1)]) + +def p_programAtomInt(p): + '''programAtom : NUMBER''' + p[0] = ConstantNumericNode(p[1], [GetPos(p, 1)]) + +def p_programAtomId(p): + '''programAtom : ATTRIBUTEID''' + p[0] = VariableNode(p[1], [GetPos(p, 1)]) + +def p_programAtomParentesis(p): + '''programAtom : LPAREN expression RPAREN''' + p[0] = p[2] + +def p_programAtomNew(p): + '''programAtom : NEW CLASSID''' + p[0] = NewStatementNode(p[2], [GetPos(p, 1)]) + + +def p_programAtomMember(p): + '''programAtom : memberCall''' + p[0] = p[1] + +def p_memberCall(p): + '''memberCall : ATTRIBUTEID LPAREN RPAREN + | ATTRIBUTEID LPAREN argumentList RPAREN''' + if len(p) == 4: + p[0] = FunctionCallStatement(VariableNode("self", p.lineno), None, p[1], [], [GetPos(p, 1)]) + else: + p[0] = FunctionCallStatement(VariableNode("self", p.lineno), None, p[1], p[3], [GetPos(p, 1)]) + +def p_argumentList(p): + '''argumentList : expression + | expression COMMA argumentList''' + if len(p) == 2: + p[0] = [p[1]] + else: + p[0] = [p[1]] + p[3] + +def p_programAtomFunction(p): + '''programAtom : programAtom functionCall''' + p[0] = FunctionCallStatement(p[1], (p[2])[0], (p[2])[1], (p[2])[2], p[1].lineNumber) + +def p_functionCall(p): + '''functionCall : DOT ATTRIBUTEID LPAREN argumentList RPAREN + | DOT ATTRIBUTEID LPAREN RPAREN + | DISPATCH CLASSID DOT ATTRIBUTEID LPAREN argumentList RPAREN + | DISPATCH CLASSID DOT ATTRIBUTEID LPAREN RPAREN''' + + if len(p) == 5: + p[0] = [None, p[2], []] + else: + if len(p) == 6: + p[0] = [None, p[2], p[4]] + else: + if len(p) == 7: + p[0] = [p[2], p[4], []] + else: + p[0] = [p[2], p[4], p[6]] + +def p_programAtomAssign(p): + '''programAtom : ATTRIBUTEID ASSIGNATION expression''' + p[0] = AssignStatementNode(VariableNode(p[1],GetPos(p,1)), p[3], [GetPos(p, 1)]) + +def p_programAtomCase(p): + '''programAtom : CASE expression OF caseBody ESAC''' + p[0] = CaseStatementNode(p[2], p[4], GetPos(p, 1)) + +def p_caseBody(p): + '''caseBody : ATTRIBUTEID COLON CLASSID ARROW expression SEMICOLON caseBody + | ATTRIBUTEID COLON CLASSID ARROW expression SEMICOLON''' + if (len(p) == 7): + p[0] = [CaseBranchNode(p[1], p[3], p[5], [GetPos(p, 3)])] + else: + p[0] = [CaseBranchNode(p[1], p[3], p[5], [GetPos(p, 3)])] + p[7] + +# produccion para expressiones let +def p_programAtomLet(p): + '''programAtom : LET letBody IN expression''' + p[0] = LetStatementNode(p[2], p[4], [GetPos(p, 1)]) + +def p_letBody(p): + '''letBody : ATTRIBUTEID COLON CLASSID + | ATTRIBUTEID COLON CLASSID ASSIGNATION expression + | ATTRIBUTEID COLON CLASSID COMMA letBody + | ATTRIBUTEID COLON CLASSID ASSIGNATION expression COMMA letBody''' + if len(p) == 4: + p[0] = [AttributeFeatureNode(p[1], p[3], None, [GetPos(p, 3)])] + else: + if len(p) == 8: + p[0] = [AttributeFeatureNode(p[1], p[3], p[5], [GetPos(p, 3)])] + p[7] + else: + if p[4] == "<-": + p[0] = [AttributeFeatureNode(p[1], p[3], p[5], [GetPos(p, 3)])] + else: + p[0] = [AttributeFeatureNode(p[1], p[3], None, [GetPos(p, 3)])] + p[5] + +def p_programAtomBlock(p): + '''programAtom : LBRACE expressionList RBRACE''' + p[0] = BlockStatementNode(p[2], [GetPos(p, 1)]) + +def p_expressionList(p): + '''expressionList : expression SEMICOLON expressionList + | expression SEMICOLON''' + if len(p) == 3: + p[0] = [p[1]] + else: + p[0] = [p[1]] + p[3] + +def p_programAtomWhile(p): + '''programAtom : WHILE expression LOOP expression POOL''' + p[0] = LoopStatementNode(p[2], p[4], [GetPos(p, 2)]) + +def p_programAtomIf(p): + '''programAtom : IF expression THEN expression ELSE expression FI''' + p[0] = ConditionalStatementNode(p[2], p[4], p[6], [GetPos(p, 1)]) + +def p_error(p): + global errors + if p is None: + errors.append("(0, 0) - SyntacticError: ERROR at or near EOF") + return + word = p.value + w = False + if p.type == 'ASSIGNATION': + word = 'ASSIGN' + w = True + if p.type == 'ESAC': + word = 'ESAC' + w = True + if p.type == 'NEW': + word = 'NEW' + w = True + if p.type == 'CLASS': + word = 'CLASS' + w = True + if w: + errors.append("(%s, %s) - SyntacticError: ERROR at or near %s " % (p.lineno, p.colno, word)) + else: + errors.append("(%s, %s) - SyntacticError: ERROR at or near \"%s\"" % (p.lineno, p.colno, word)) + pass + + +parser = yacc.yacc(debug=1) + +def parse(code): + global errors + errors = [] + result = parser.parse(code) + return result, errors diff --git a/src/parsetab.py b/src/parsetab.py new file mode 100644 index 00000000..2c57179a --- /dev/null +++ b/src/parsetab.py @@ -0,0 +1,94 @@ + +# parsetab.py +# This file is automatically generated. Do not edit. +_tabversion = '3.10' + +_lr_method = 'LALR' + +_lr_signature = 'programNUMBER STRING PLUS MINUS TIMES DIVIDE LPAREN RPAREN ATTRIBUTEID CLASSID LBRACE RBRACE COMMA SEMICOLON COLON ASSIGNATION ARROW DOT LESS LESSEQUAL GREATER GREATEREQUAL EQUAL COMPLEMENT DISPATCH CLASS ELSE FALSE FI IF INHERITS IN ISVOID LET LOOP POOL THEN WHILE CASE ESAC NEW OF NOT TRUEprogram : classListclassList : classDefinition classList\n | classDefinitionclassDefinition : CLASS CLASSID LBRACE classFeatureList RBRACE SEMICOLON\n | CLASS CLASSID INHERITS CLASSID LBRACE classFeatureList RBRACE SEMICOLONempty :classFeatureList : feature classFeatureList\n | emptyfeature : attributeFeature\n | functionFeatureattributeFeature : ATTRIBUTEID COLON CLASSID SEMICOLON\n | ATTRIBUTEID COLON CLASSID ASSIGNATION expression SEMICOLONfunctionFeature : ATTRIBUTEID LPAREN parameterList RPAREN COLON CLASSID LBRACE expression RBRACE SEMICOLON\n | ATTRIBUTEID LPAREN RPAREN COLON CLASSID LBRACE expression RBRACE SEMICOLONparameterList : parameter COMMA parameterList\n | parameterparameter : ATTRIBUTEID COLON CLASSIDexpression : notForm\n | mixedExpressionnotForm : NOT mixedExpressionmixedExpression : mixedExpression LESSEQUAL arithmeticExpression\n | mixedExpression LESS arithmeticExpression\n | mixedExpression EQUAL expression\n | arithmeticExpressionarithmeticExpression : arithmeticExpression PLUS term\n | arithmeticExpression MINUS term\n | termterm : term TIMES isvoidForm\n | term DIVIDE isvoidForm\n | isvoidFormisvoidForm : ISVOID expression\n | complementFormcomplementForm : COMPLEMENT expression\n | programAtomprogramAtom : TRUE\n | FALSEprogramAtom : STRINGprogramAtom : NUMBERprogramAtom : ATTRIBUTEIDprogramAtom : LPAREN expression RPARENprogramAtom : NEW CLASSIDprogramAtom : memberCallmemberCall : ATTRIBUTEID LPAREN RPAREN\n | ATTRIBUTEID LPAREN argumentList RPARENargumentList : expression\n | expression COMMA argumentListprogramAtom : programAtom functionCallfunctionCall : DOT ATTRIBUTEID LPAREN argumentList RPAREN\n | DOT ATTRIBUTEID LPAREN RPAREN\n | DISPATCH CLASSID DOT ATTRIBUTEID LPAREN argumentList RPAREN\n | DISPATCH CLASSID DOT ATTRIBUTEID LPAREN RPARENprogramAtom : ATTRIBUTEID ASSIGNATION expressionprogramAtom : CASE expression OF caseBody ESACcaseBody : ATTRIBUTEID COLON CLASSID ARROW expression SEMICOLON caseBody\n | ATTRIBUTEID COLON CLASSID ARROW expression SEMICOLONprogramAtom : LET letBody IN expressionletBody : ATTRIBUTEID COLON CLASSID\n | ATTRIBUTEID COLON CLASSID ASSIGNATION expression\n | ATTRIBUTEID COLON CLASSID COMMA letBody\n | ATTRIBUTEID COLON CLASSID ASSIGNATION expression COMMA letBodyprogramAtom : LBRACE expressionList RBRACEexpressionList : expression SEMICOLON expressionList\n | expression SEMICOLONprogramAtom : WHILE expression LOOP expression POOLprogramAtom : IF expression THEN expression ELSE expression FI' + +_lr_action_items = {'CLASS':([0,3,21,63,],[4,4,-4,-5,]),'$end':([1,2,3,5,21,63,],[0,-1,-3,-2,-4,-5,]),'CLASSID':([4,8,18,30,32,52,60,79,107,132,],[6,15,22,59,61,81,89,103,121,141,]),'LBRACE':([6,15,29,39,43,45,51,54,56,57,58,61,64,65,67,68,69,71,72,73,74,89,90,106,109,110,111,112,115,116,133,136,140,148,],[7,20,56,56,56,56,56,56,56,56,56,90,56,56,56,56,56,56,56,56,56,112,56,56,56,56,56,56,56,56,56,56,56,56,]),'INHERITS':([6,],[8,]),'RBRACE':([7,9,10,11,12,13,17,20,27,28,35,37,38,40,41,42,44,46,47,48,49,50,53,66,70,75,76,77,81,85,91,92,95,96,97,98,99,100,101,104,108,109,113,114,120,122,125,129,131,135,138,139,145,147,150,151,],[-6,16,-6,-8,-9,-10,-7,-6,34,-11,-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-12,-20,-31,-33,-47,-41,108,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-63,126,-44,-56,-62,137,-49,-53,-64,-14,-48,-13,-51,-65,-50,]),'ATTRIBUTEID':([7,10,12,13,19,20,28,29,33,39,43,45,51,54,55,56,57,58,64,65,66,67,68,69,71,72,73,74,78,90,105,106,109,110,111,112,115,116,117,133,134,136,138,140,145,148,149,154,],[14,14,-9,-10,23,14,-11,35,23,35,35,35,35,35,84,35,35,35,35,35,-12,35,35,35,35,35,35,35,102,35,119,35,35,35,35,35,35,35,130,35,84,35,-14,35,-13,35,84,119,]),'COLON':([14,23,25,31,84,119,],[18,30,32,60,107,132,]),'LPAREN':([14,29,35,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,102,106,109,110,111,112,115,116,130,133,136,140,148,],[19,51,65,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,116,51,51,51,51,51,51,51,140,51,51,51,51,]),'SEMICOLON':([16,22,34,35,36,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,86,91,92,95,96,97,98,99,100,101,104,108,114,120,126,129,131,135,137,139,147,150,151,152,],[21,28,63,-39,66,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,109,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,138,-49,-53,-64,145,-48,-51,-65,-50,154,]),'RPAREN':([19,24,26,35,37,38,40,41,42,44,46,47,48,49,50,53,59,62,65,70,75,76,77,80,81,91,92,93,94,95,96,97,98,99,100,101,104,108,114,116,120,127,128,129,131,135,139,140,146,147,150,151,],[25,31,-16,-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-17,-15,92,-20,-31,-33,-47,104,-41,-52,-43,114,-45,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,129,-56,-46,139,-49,-53,-64,-48,147,151,-51,-65,-50,]),'ASSIGNATION':([22,35,121,],[29,64,133,]),'COMMA':([26,35,37,38,40,41,42,44,46,47,48,49,50,53,59,70,75,76,77,81,91,92,94,95,96,97,98,99,100,101,104,108,114,120,121,129,131,135,139,142,147,150,151,],[33,-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-17,-20,-31,-33,-47,-41,-52,-43,115,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,134,-49,-53,-64,-48,149,-51,-65,-50,]),'NOT':([29,43,45,51,54,56,57,58,64,65,69,90,106,109,110,111,112,115,116,133,136,140,148,],[39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,39,]),'ISVOID':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,]),'COMPLEMENT':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,]),'TRUE':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,]),'FALSE':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,]),'STRING':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'NUMBER':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,]),'NEW':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,52,]),'CASE':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,54,]),'LET':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,]),'WHILE':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,]),'IF':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,58,]),'DOT':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,103,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,78,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,117,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'DISPATCH':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,79,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'TIMES':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,73,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,73,73,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'DIVIDE':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,74,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,74,74,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'PLUS':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,71,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,71,71,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'MINUS':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,72,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,72,72,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'LESSEQUAL':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,67,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,67,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'LESS':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,68,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,68,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'EQUAL':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,69,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,69,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'OF':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,82,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,105,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'LOOP':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,87,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,110,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'THEN':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,88,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,111,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,-51,-65,-50,]),'POOL':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,123,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,135,-49,-53,-64,-48,-51,-65,-50,]),'ELSE':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,124,129,131,135,139,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,136,-49,-53,-64,-48,-51,-65,-50,]),'IN':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,83,91,92,95,96,97,98,99,100,101,104,108,114,120,121,129,131,135,139,142,143,147,150,151,153,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,106,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-57,-49,-53,-64,-48,-58,-59,-51,-65,-50,-60,]),'FI':([35,37,38,40,41,42,44,46,47,48,49,50,53,70,75,76,77,81,91,92,95,96,97,98,99,100,101,104,108,114,120,129,131,135,139,144,147,150,151,],[-39,-18,-19,-24,-27,-30,-32,-34,-35,-36,-37,-38,-42,-20,-31,-33,-47,-41,-52,-43,-21,-22,-23,-25,-26,-28,-29,-40,-61,-44,-56,-49,-53,-64,-48,150,-51,-65,-50,]),'ESAC':([118,154,155,],[131,-55,-54,]),'ARROW':([141,],[148,]),} + +_lr_action = {} +for _k, _v in _lr_action_items.items(): + for _x,_y in zip(_v[0],_v[1]): + if not _x in _lr_action: _lr_action[_x] = {} + _lr_action[_x][_k] = _y +del _lr_action_items + +_lr_goto_items = {'program':([0,],[1,]),'classList':([0,3,],[2,5,]),'classDefinition':([0,3,],[3,3,]),'classFeatureList':([7,10,20,],[9,17,27,]),'feature':([7,10,20,],[10,10,10,]),'empty':([7,10,20,],[11,11,11,]),'attributeFeature':([7,10,20,],[12,12,12,]),'functionFeature':([7,10,20,],[13,13,13,]),'parameterList':([19,33,],[24,62,]),'parameter':([19,33,],[26,26,]),'expression':([29,43,45,51,54,56,57,58,64,65,69,90,106,109,110,111,112,115,116,133,136,140,148,],[36,75,76,80,82,86,87,88,91,94,97,113,120,86,123,124,125,94,94,142,144,94,152,]),'notForm':([29,43,45,51,54,56,57,58,64,65,69,90,106,109,110,111,112,115,116,133,136,140,148,],[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,]),'mixedExpression':([29,39,43,45,51,54,56,57,58,64,65,69,90,106,109,110,111,112,115,116,133,136,140,148,],[38,70,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,]),'arithmeticExpression':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,90,106,109,110,111,112,115,116,133,136,140,148,],[40,40,40,40,40,40,40,40,40,40,40,95,96,40,40,40,40,40,40,40,40,40,40,40,40,40,]),'term':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,90,106,109,110,111,112,115,116,133,136,140,148,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,98,99,41,41,41,41,41,41,41,41,41,41,41,41,]),'isvoidForm':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,100,101,42,42,42,42,42,42,42,42,42,42,42,42,]),'complementForm':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,44,]),'programAtom':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,46,]),'memberCall':([29,39,43,45,51,54,56,57,58,64,65,67,68,69,71,72,73,74,90,106,109,110,111,112,115,116,133,136,140,148,],[53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,]),'functionCall':([46,],[77,]),'letBody':([55,134,149,],[83,143,153,]),'expressionList':([56,109,],[85,122,]),'argumentList':([65,115,116,140,],[93,127,128,146,]),'caseBody':([105,154,],[118,155,]),} + +_lr_goto = {} +for _k, _v in _lr_goto_items.items(): + for _x, _y in zip(_v[0], _v[1]): + if not _x in _lr_goto: _lr_goto[_x] = {} + _lr_goto[_x][_k] = _y +del _lr_goto_items +_lr_productions = [ + ("S' -> program","S'",1,None,None,None), + ('program -> classList','program',1,'p_program','my_parser.py',17), + ('classList -> classDefinition classList','classList',2,'p_classList','my_parser.py',21), + ('classList -> classDefinition','classList',1,'p_classList','my_parser.py',22), + ('classDefinition -> CLASS CLASSID LBRACE classFeatureList RBRACE SEMICOLON','classDefinition',6,'p_classDefinition','my_parser.py',29), + ('classDefinition -> CLASS CLASSID INHERITS CLASSID LBRACE classFeatureList RBRACE SEMICOLON','classDefinition',8,'p_classDefinition','my_parser.py',30), + ('empty -> ','empty',0,'p_empty','my_parser.py',37), + ('classFeatureList -> feature classFeatureList','classFeatureList',2,'p_classFeatureList','my_parser.py',41), + ('classFeatureList -> empty','classFeatureList',1,'p_classFeatureList','my_parser.py',42), + ('feature -> attributeFeature','feature',1,'p_feature','my_parser.py',50), + ('feature -> functionFeature','feature',1,'p_feature','my_parser.py',51), + ('attributeFeature -> ATTRIBUTEID COLON CLASSID SEMICOLON','attributeFeature',4,'p_attributeFeature','my_parser.py',55), + ('attributeFeature -> ATTRIBUTEID COLON CLASSID ASSIGNATION expression SEMICOLON','attributeFeature',6,'p_attributeFeature','my_parser.py',56), + ('functionFeature -> ATTRIBUTEID LPAREN parameterList RPAREN COLON CLASSID LBRACE expression RBRACE SEMICOLON','functionFeature',10,'p_functionFeature','my_parser.py',63), + ('functionFeature -> ATTRIBUTEID LPAREN RPAREN COLON CLASSID LBRACE expression RBRACE SEMICOLON','functionFeature',9,'p_functionFeature','my_parser.py',64), + ('parameterList -> parameter COMMA parameterList','parameterList',3,'p_parameterList','my_parser.py',71), + ('parameterList -> parameter','parameterList',1,'p_parameterList','my_parser.py',72), + ('parameter -> ATTRIBUTEID COLON CLASSID','parameter',3,'p_parameter','my_parser.py',79), + ('expression -> notForm','expression',1,'p_expression','my_parser.py',83), + ('expression -> mixedExpression','expression',1,'p_expression','my_parser.py',84), + ('notForm -> NOT mixedExpression','notForm',2,'p_notForm','my_parser.py',88), + ('mixedExpression -> mixedExpression LESSEQUAL arithmeticExpression','mixedExpression',3,'p_mixedExpression','my_parser.py',95), + ('mixedExpression -> mixedExpression LESS arithmeticExpression','mixedExpression',3,'p_mixedExpression','my_parser.py',96), + ('mixedExpression -> mixedExpression EQUAL expression','mixedExpression',3,'p_mixedExpression','my_parser.py',97), + ('mixedExpression -> arithmeticExpression','mixedExpression',1,'p_mixedExpression','my_parser.py',98), + ('arithmeticExpression -> arithmeticExpression PLUS term','arithmeticExpression',3,'p_arithmeticExpression','my_parser.py',111), + ('arithmeticExpression -> arithmeticExpression MINUS term','arithmeticExpression',3,'p_arithmeticExpression','my_parser.py',112), + ('arithmeticExpression -> term','arithmeticExpression',1,'p_arithmeticExpression','my_parser.py',113), + ('term -> term TIMES isvoidForm','term',3,'p_term','my_parser.py',123), + ('term -> term DIVIDE isvoidForm','term',3,'p_term','my_parser.py',124), + ('term -> isvoidForm','term',1,'p_term','my_parser.py',125), + ('isvoidForm -> ISVOID expression','isvoidForm',2,'p_isvoidForm','my_parser.py',135), + ('isvoidForm -> complementForm','isvoidForm',1,'p_isvoidForm','my_parser.py',136), + ('complementForm -> COMPLEMENT expression','complementForm',2,'p_complementForm','my_parser.py',143), + ('complementForm -> programAtom','complementForm',1,'p_complementForm','my_parser.py',144), + ('programAtom -> TRUE','programAtom',1,'p_programAtomBoolean','my_parser.py',151), + ('programAtom -> FALSE','programAtom',1,'p_programAtomBoolean','my_parser.py',152), + ('programAtom -> STRING','programAtom',1,'p_programAtomString','my_parser.py',156), + ('programAtom -> NUMBER','programAtom',1,'p_programAtomInt','my_parser.py',160), + ('programAtom -> ATTRIBUTEID','programAtom',1,'p_programAtomId','my_parser.py',164), + ('programAtom -> LPAREN expression RPAREN','programAtom',3,'p_programAtomParentesis','my_parser.py',168), + ('programAtom -> NEW CLASSID','programAtom',2,'p_programAtomNew','my_parser.py',172), + ('programAtom -> memberCall','programAtom',1,'p_programAtomMember','my_parser.py',177), + ('memberCall -> ATTRIBUTEID LPAREN RPAREN','memberCall',3,'p_memberCall','my_parser.py',181), + ('memberCall -> ATTRIBUTEID LPAREN argumentList RPAREN','memberCall',4,'p_memberCall','my_parser.py',182), + ('argumentList -> expression','argumentList',1,'p_argumentList','my_parser.py',189), + ('argumentList -> expression COMMA argumentList','argumentList',3,'p_argumentList','my_parser.py',190), + ('programAtom -> programAtom functionCall','programAtom',2,'p_programAtomFunction','my_parser.py',197), + ('functionCall -> DOT ATTRIBUTEID LPAREN argumentList RPAREN','functionCall',5,'p_functionCall','my_parser.py',201), + ('functionCall -> DOT ATTRIBUTEID LPAREN RPAREN','functionCall',4,'p_functionCall','my_parser.py',202), + ('functionCall -> DISPATCH CLASSID DOT ATTRIBUTEID LPAREN argumentList RPAREN','functionCall',7,'p_functionCall','my_parser.py',203), + ('functionCall -> DISPATCH CLASSID DOT ATTRIBUTEID LPAREN RPAREN','functionCall',6,'p_functionCall','my_parser.py',204), + ('programAtom -> ATTRIBUTEID ASSIGNATION expression','programAtom',3,'p_programAtomAssign','my_parser.py',218), + ('programAtom -> CASE expression OF caseBody ESAC','programAtom',5,'p_programAtomCase','my_parser.py',222), + ('caseBody -> ATTRIBUTEID COLON CLASSID ARROW expression SEMICOLON caseBody','caseBody',7,'p_caseBody','my_parser.py',226), + ('caseBody -> ATTRIBUTEID COLON CLASSID ARROW expression SEMICOLON','caseBody',6,'p_caseBody','my_parser.py',227), + ('programAtom -> LET letBody IN expression','programAtom',4,'p_programAtomLet','my_parser.py',235), + ('letBody -> ATTRIBUTEID COLON CLASSID','letBody',3,'p_letBody','my_parser.py',239), + ('letBody -> ATTRIBUTEID COLON CLASSID ASSIGNATION expression','letBody',5,'p_letBody','my_parser.py',240), + ('letBody -> ATTRIBUTEID COLON CLASSID COMMA letBody','letBody',5,'p_letBody','my_parser.py',241), + ('letBody -> ATTRIBUTEID COLON CLASSID ASSIGNATION expression COMMA letBody','letBody',7,'p_letBody','my_parser.py',242), + ('programAtom -> LBRACE expressionList RBRACE','programAtom',3,'p_programAtomBlock','my_parser.py',255), + ('expressionList -> expression SEMICOLON expressionList','expressionList',3,'p_expressionList','my_parser.py',259), + ('expressionList -> expression SEMICOLON','expressionList',2,'p_expressionList','my_parser.py',260), + ('programAtom -> WHILE expression LOOP expression POOL','programAtom',5,'p_programAtomWhile','my_parser.py',267), + ('programAtom -> IF expression THEN expression ELSE expression FI','programAtom',7,'p_programAtomIf','my_parser.py',271), +] diff --git a/src/type_builder.py b/src/type_builder.py new file mode 100644 index 00000000..b3f294ab --- /dev/null +++ b/src/type_builder.py @@ -0,0 +1,95 @@ +import visitor +import ast_hierarchy +import context + + +class TypeBuilderVisitor: + def __init__(self, context): + self.context = context + self.current_type = None # type(current_type) = Type + self.count = 0 + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(ast_hierarchy.ProgramNode) + def visit(self, node, errors): + for _class in node.classes: + self.visit(_class, errors) + + @visitor.when(ast_hierarchy.ClassNode) + def visit(self, node, errors): + + if node.typeName in ["Bool", "Int", "String", "Object"] : + errors.append("SemanticError: Redefinition of basic class " + node.typeName + ". ") + return + + if node.fatherTypeName is None: + node.fatherTypeName = 'Object' + + elif node.fatherTypeName in ["Bool", "Int", "String"]: + errors.append("SemanticError: Class " + node.typeName + " cannot inherit class " + node.fatherTypeName + "." ) + return + + if not self.context.Hierarchy.keys().__contains__(node.fatherTypeName): + errors.append("Undefined class") + return + + if node.fatherTypeName is None and node.typeName != 'Object': + node.fatherTypeName = 'Object' + + node.fatherTypeName = self.context.Hierarchy[node.fatherTypeName] + self.context.Hierarchy[node.typeName].Parent = node.fatherTypeName + + self.current_type = self.context.Hierarchy[node.typeName] + + for f in node.features: + self.visit(f, errors) + + + @visitor.when(ast_hierarchy.AttributeFeatureNode) + def visit(self, node, errors): + #attribute can be self type? + if node.id == 'self': + errors.append("SemanticError: 'self' cannot be the name of an attribute.") + return + if not self.context.Hierarchy.keys().__contains__(node.typeName): + errors.append("TypeError: Class " + node.typeName + " of attribute " + node.id + " is undefined.") + return + # if not parent is None and parent.DefineInHierarchy(node.id): + # errors.append("SemanticError: Attribute x is an attribute of an inherited class.") + # return + ans = self.current_type.DefineAttr(node.id, self.context.Hierarchy[node.typeName]) + + if ans is None: + errors.append("SemanticError: Attribute " + node.id + " is multiply redefined in class " + self.current_type.Name + ".") + + @visitor.when(ast_hierarchy.FunctionFeatureNode) + def visit(self, node, errors): + # return can be self type? + if self.context.Hierarchy.keys().__contains__(node.typeName): + argument_list = [] + for parameter in node.parameters: + if parameter.id in argument_list or parameter.id == self: + errors.append("Sintactic error: Formal Parameter is multiply redefined") + pass + argument_list.append(parameter.id) + + argument_types = [] + for parameter in node.parameters: + param_name = parameter.id + param_type = parameter.typeName + if self.context.Hierarchy.keys().__contains__(param_type): + argument_types.append(param_type) + else: + errors.append("TypeError") + + child_context = self.context.CreateChildContext() + + ans = self.current_type.DefineMeth(node.id , argument_list, argument_types, node.typeName, "func_" + node.id + "_" + str(self.count), child_context) + if ans is None: + count += 1 + errors.append("SemanticError: multiply defined methd") + else: + errors.append("return type missing") diff --git a/src/type_checker.py b/src/type_checker.py new file mode 100644 index 00000000..ad1c721a --- /dev/null +++ b/src/type_checker.py @@ -0,0 +1,455 @@ + +import visitor +import ast_hierarchy +import context + +# To Do list: +# *Hacer los visit de Method y Attr +# *Poner la linea a todos + +class TypeCheckerVisitor: + def __init__(self): + self.current_type = None # type(current_type) = Type + + @visitor.on('node') + def visit(self, node, context, errors): + pass + + # [Program] + @visitor.when(ast_hierarchy.ProgramNode) + def visit(self, node, context, errors): + ''' + In this method is where we start the visitor over + the ast_hierarchy, checking all classes and last the main class + and it's main method. + ''' + # build the types_graph + context.BuildTypesHierarchy() + # check if Program has a clas Main with a local method main + context.CheckMain() + # check if are not cycles in the inheritance graph + context.IsTree(errors) + if len(errors) > 0: + return + # check inheritance features and build LCA preprocessing + + # check if classes are ok + + for _class in node.classes: + child_context = context.CreateChildContext() + self.visit(_class, child_context, errors) + + # [Class] + @visitor.when(ast_hierarchy.ClassNode) + def visit(self, node, context, errors): + self.current_type = context.GetType(node.typeName) + + # adding to the current enviroment all the class attributes + parent = self.current_type.Parent + for attr in self.current_type.AttrList: + #verificar que el attr no exista en ningun ancestro antes de crearlo + if attr.Name == 'self' or not parent.IsDefineAttr2(attr, parent): + _attr = context.DefineVar(attr.Name, attr.Type, None) + else: + errors.append("error") + return + for meth_name in self.current_type.MethList: + meth = self.current_type.MethList[meth_name] + parent_meth = context.IsDefineMeth2(self.current_type.Parent, meth_name) + if meth is not None: + if parent_meth is not None: + if parent_meth.ReturnType != meth.ReturnType: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: In redefined method " + meth.Name + ", return type " + meth.ReturnType + "is different from original return type " + parent_meth.ReturnType + ". ") + return + if len(parent_meth.ParamsName) != len(meth.ParamsName): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: Incompatible number of formal parameters in redefined method " + meth.Name + ".") + return + for i in range(len(meth.ParamsName)): + if meth.ParamsType[i] != parent_meth.ParamsType[i]: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: In redefined method " + meth.Name + ", parameter type " + meth.ParamsType[i] + " is different from original type " + parent_meth.ParamsType[i] + ".") + return + for i in range(len(meth.ParamsName)): + param_name = meth.ParamsName[i] + param_type = meth.ParamsType[i] + var = meth.Context.DefineVar(param_name, param_type) + + for _f in node.features: + child_context = context.CreateChildContext() + self.visit(_f, child_context, errors) + + + + + @visitor.when(ast_hierarchy.FunctionFeatureNode) + def visit(self, node, context, errors): + node.ComputedType = [] + meth = context.IsDefineMeth2(self.current_type, node.id) + self.visit(node.statements, meth.Context, errors) + node.ComputedType = node.statements.ComputedType + for _type in node.ComputedType: + if not (node.typeName == _type.Name or context.IsDerived( _type.Name, node.typeName)): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Inferred return type " + _type.Name +" of method " + node.id + " does not conform to declared type " + node.typeName + ".") + meth.ComputedType = node.ComputedType + + @visitor.when(ast_hierarchy.FunctionCallStatement) + def visit(self, node, context, errors): + node.ComputedType = [] + d = node.dispatchType + self.visit(node.instance, context, errors) + instance_type = context.GetType(node.instance.typeName) if node.instance.typeName != 'self' else self.current_type + if d is not None: + #revisar si d es padre de instance, en caso positivo, hacer instance igual a d + if not (d == instance_type.Name or context.IsDerived( d, instance_type.Name)): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Expression type " + instance_type.Name + "does not conform to declared static dispatch type " + d +". ") + #en caso negativo lanzar error que debe imprimir dispatch6 + + meth = context.IsDefineMeth2(instance_type, node.function) + if meth is not None: + if len(meth.ParamsName) != len(node.args): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: Method " + meth.Name + " called with wrong number of arguments. ") + for i in range(len(meth.ParamsName)): + var_name = meth.ParamsName[i] + var = meth.Context.Variables[var_name] + param_type = var.Type + arg = node.args[i] + self.visit(arg, context, errors) + for _type in arg.ComputedType: + if not (param_type == _type.Name or context.IsDerived( _type.Name, param_type)): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: In call of method " + meth.Name +", type " + _type.Name + " of parameter " + var_name + " does not conform to declared type " + param_type + ".") + break + self.visit(node.instance, meth.Context, errors) + node.typeName = meth.ReturnType + node.ComputedType = [context.GetType(meth.ReturnType)] + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - AttributeError: Dispatch to undefined method " + node.function + ". ") + + @visitor.when(ast_hierarchy.AttributeFeatureNode) + def visit(self, node, context, errors): + node.ComputedType = [] + + if (not context.Hierarchy.__contains__(node.typeName)): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Class " + node.typeName + " of identifier " + node.id + " is undefined.") + if node.expression is not None: + node.ComputedType = [] + self.visit(node.expression, context, errors) + #revisar si debo preguntar por el typeName o por el ComputedType + for _type in node.expression.ComputedType: + if not (node.typeName == _type.Name or context.IsDerived( _type.Name, node.typeName)): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Inferred type " + _type.Name +" of initialization of " + node.id + " does not conform to identifier's declared type " + node.typeName + ".") + else: + node.ComputedType.append(_type) + attr = context.Variables[node.id] + attr.ComputedType = node.ComputedType + + @visitor.when(ast_hierarchy.NewStatementNode) + def visit(self, node, context, errors): + _type = context.GetType(node.typeName) + if not _type is None: + node.ComputedType = [_type] + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: 'new' used with undefined class " + node.typeName + ".") + + @visitor.when(ast_hierarchy.ConditionalStatementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + + self.visit(node.ifExpr, context, errors) + self.visit(node.evalExpr, context, errors) + self.visit(node.elseExpr, context, errors) + node.typeName = node.evalExpr.typeName if context.IsDerived(node.elseExpr.typeName, node.ifExpr.typeName) else node.elseExpr.typeName + for _type in node.evalExpr.ComputedType: + if (_type.Name != "Bool"): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Predicate of 'if' does not have type Bool.") + node.ComputedType = node.ifExpr.ComputedType + node.elseExpr.ComputedType + + @visitor.when(ast_hierarchy.LoopStatementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = 'null' + self.visit(node.loopExpr, context, errors) + self.visit(node.evalExpr, context, errors) + for _type in node.evalExpr.ComputedType: + if _type.Name != "Bool": + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Loop condition does not have type Bool.") + return + + node.ComputedType = node.loopExpr.ComputedType + + @visitor.when(ast_hierarchy.BlockStatementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + + for _expr in node.expressions: + self.visit(_expr,context, errors) + + node.ComputedType = node.expressions[-1].ComputedType + node.typeName = node.expressions[-1].typeName + + + @visitor.when(ast_hierarchy.VariableNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = 'error' + + if (node.lex == 'self'): + node.typeName = self.current_type.Name + node.ComputedType = [context.GetType(node.typeName)] + else: + node.ComputedType = [] + _var = context.GetAttr(self.current_type, node.lex) + if _var is None: + if context.Variables.__contains__(node.lex): + _var = context.Variables[node.lex] + node.typeName = _var.Type + node.ComputedType = [context.GetType(node.typeName)] + + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - NameError: Undefined identifier " + node.lex) + else: + node.typeName = _var.Type + node.ComputedType = [context.GetType(node.typeName)] + + @visitor.when(ast_hierarchy.LetStatementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + + child_context = context.CreateChildContext() + child_context.Variables = {} + for _var in node.variables: + if _var.id == 'self': + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: 'self' cannot be bound in a 'let' expression.") + return + ans = child_context.DefineVar(_var.id, _var.typeName) + self.visit(_var,child_context, errors) + self.visit(node.expression,child_context, errors) + node.ComputedType = node.expression.ComputedType + node.typeName = node.expression.typeName + + @visitor.when(ast_hierarchy.CaseStatementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + + self.visit(node.expression, context, errors) + #Implementar lo que pasara con el body + _types = [] + for x in node.body: + if _types.__contains__(x.typeName): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: Duplicate branch " + x.typeName + " in case statement.") + return + self.visit(x, context, errors) + _types.append(x.typeName) + node.ComputedType = node.ComputedType + x.ComputedType + node.typeName = 'Object' + #chaquear que el retorno no sea void + + @visitor.when(ast_hierarchy.CaseBranchNode) + def visit(self, node, context, errors): + node.ComputedType = [] + if not context.Hierarchy.keys().__contains__(node.typeName): + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Class " + node.typeName + " of case branch is undefined.") + return + self.visit(node.expression, context, errors) + node.ComputedType = node.expression.ComputedType + #Responder: + #En que momento hacer chequeo de tipos + #Quienes son id, type + + @visitor.when(ast_hierarchy.AssignStatementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error" + if node.id.lex == 'self': + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - SemanticError: Cannot assign to 'self'.") + self.visit(node.id, context, errors) + self.visit(node.expression, context, errors) + #pedir el atributo que se llama node.id y verificar sus tipos para ver si es posible hacer la asignación + for _type in node.expression.ComputedType: + #if coinciden los tipos del id y de la expresion: + + attr = None + for var in context.Variables.keys(): + toks = var.split() + t = toks[-1] + if len(toks) == 1 or toks[1] == node.id.lex: + attr = context.Variables[var] + break + if attr is None: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - Undefined identifier "+ node.id.lex + ".") + return + if not attr.Name == 'self' and not (attr.Type == _type.Name or context.IsDerived( _type.Name, attr.Type)): + node.typeName = "error in assign" + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - Not matching type for assignment in " + attr.Type + "=" + _type.Name ) + else: + node.ComputedType.append(_type) + node.typeName = attr.Type + + + + + + #Unary Operations + @visitor.when(ast_hierarchy.ComplementNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error in complement" + self.visit(node.expression,context, errors) + for _type in node.expression.ComputedType: + if (_type.Name != "Int"): + node.typeName = "error in complement" + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Argument of '~' has type " + _type.Name + " instead of Int.") + else: + node.ComputedType = [context.Hierarchy.get("Int")] + + @visitor.when(ast_hierarchy.IsVoidNode) + def visit(self,node, context, errors): + node.typeName = "Bool" + + self.visit(node.expression, context, errors) + node.ComputedType = [context.Hierarchy.get("Bool")] + + @visitor.when(ast_hierarchy.NotNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error in not" + self.visit(node.expression, context, errors) + for _type in node.expression.ComputedType: + if (_type.Name != "Bool"): + node.typeName = "error in not" + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: Argument of 'not' has type " + _type.Name + " instead of Bool.") + else: + node.ComputedType = [context.Hierarchy.get("Bool") ] + + + + #Binary int expressions + @visitor.when(ast_hierarchy.PlusNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error in plus" + + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + left_type = node.left.ComputedType + right_type = node.right.ComputedType + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == "Int" and right_type.Name == "Int"): + node.ComputedType = [context.Hierarchy.get("Int")] + node.typeName = "Int" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " + " + right_type.Name) + + @visitor.when(ast_hierarchy.MinusNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error in minus" + + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + left_type = node.left.ComputedType + right_type = node.right.ComputedType + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == "Int" and right_type.Name == "Int"): + node.ComputedType = [context.Hierarchy.get("Int")] + node.typeName = "Int" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " - " + right_type.Name) + + @visitor.when(ast_hierarchy.TimesNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error in times" + + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == "Int" and right_type.Name == "Int"): + node.ComputedType = [context.Hierarchy.get("Int")] + node.typeName = "Int" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " * " + right_type.Name) + + @visitor.when(ast_hierarchy.DivideNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error in div" + + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == "Int" and right_type.Name == "Int"): + node.ComputedType = [context.Hierarchy.get("Int")] + node.typeName = "Int" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " / " + right_type.Name) + + + + #Binary bool expressions + @visitor.when(ast_hierarchy.EqualNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error =" + + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == right_type.Name and left_type.Name in ["Int", "Bool", "String"]): + node.ComputedType = [context.Hierarchy.get("Bool")] + node.typeName = "Bool" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " = " + right_type.Name) + + @visitor.when(ast_hierarchy.LessNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error <" + + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == right_type.Name and left_typeName in ["Int", "Bool", "String"]): + node.ComputedType = [context.Hierarchy.get("Bool")] + node.typeName = "Bool" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " < " + right_type.Name) + + @visitor.when(ast_hierarchy.LessEqualNode) + def visit(self, node, context, errors): + node.ComputedType = [] + node.typeName = "error <=" + self.visit(node.left, context, errors) + self.visit(node.right, context, errors) + for left_type in node.left.ComputedType: + for right_type in node.right.ComputedType: + if (left_type.Name == right_type.Name and left_typeName in ["Int", "Bool", "String"]): + + node.ComputedType = [context.Hierarchy.get("Bool")] + node.typeName = "Bool" + else: + errors.append("(" +str(node.getLineNumber())+ ","+ str(node.getColumnNumber()) +") - TypeError: non-Int arguments: " + left_type.Name + " <= " + right_type.Name) + + + #Ctes + @visitor.when(ast_hierarchy.ConstantNumericNode) + def visit(self, node, context, errors): + node.ComputedType = [context.Hierarchy.get("Int")] + node.typeName = "Int" + node.ComputedType = [context.GetType(node.typeName)] + + @visitor.when(ast_hierarchy.ConstantBoolNode) + def visit(self, node, context, errors): + node.ComputedType = [context.Hierarchy.get("Bool")] + node.typeName = "Bool" + node.ComputedType = [context.GetType(node.typeName)] + + @visitor.when(ast_hierarchy.ConstantStringNode) + def visit(self, node, context, errors): + node.ComputedType = [context.Hierarchy.get("String")] + node.typeName = "String" + node.ComputedType = [context.GetType(node.typeName)] \ No newline at end of file diff --git a/src/type_collector.py b/src/type_collector.py new file mode 100644 index 00000000..f79904c6 --- /dev/null +++ b/src/type_collector.py @@ -0,0 +1,28 @@ +import visitor +import ast_hierarchy +import context + + +class TypeCollectorVisitor: + def __init__(self): + self.Context = None + self.BasicClasses = ["Object", "IO", "Int", "String", "Bool"] + + @visitor.on('node') + def visit(self, node): + pass + + @visitor.when(ast_hierarchy.ProgramNode) + def visit(self, node, errors): + self.Context = context.Context(None) + + for _class in node.classes: + self.visit(_class, errors) + + @visitor.when(ast_hierarchy.ClassNode) + def visit(self, node, errors): + if self.Context.Hierarchy.keys().__contains__(node.typeName): + errors.append("SemanticError: Redefinition of basic class " + node.typeName + ". ") + else: + self.Context.Hierarchy[node.typeName] = self.Context.DefineType(node.typeName, node.fatherTypeName) + \ No newline at end of file diff --git a/src/visitor.py b/src/visitor.py new file mode 100644 index 00000000..79f34db3 --- /dev/null +++ b/src/visitor.py @@ -0,0 +1,87 @@ +# The MIT License (MIT) +# +# Copyright (c) 2013 Curtis Schlak +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import inspect + +__all__ = ['on', 'when'] + +def on(param_name): + def f(fn): + dispatcher = Dispatcher(param_name, fn) + return dispatcher + + return f + + +def when(param_type): + def f(fn): + frame = inspect.currentframe().f_back + func_name = fn.func_name if 'func_name' in dir(fn) else fn.__name__ + dispatcher = frame.f_locals[func_name] + if not isinstance(dispatcher, Dispatcher): + dispatcher = dispatcher.dispatcher + dispatcher.add_target(param_type, fn) + + def ff(*args, **kw): + return dispatcher(*args, **kw) + + ff.dispatcher = dispatcher + return ff + + return f + + +class Dispatcher(object): + def __init__(self, param_name, fn): + frame = inspect.currentframe().f_back.f_back + top_level = frame.f_locals == frame.f_globals + self.param_index = self.__argspec(fn).args.index(param_name) + self.param_name = param_name + self.targets = {} + + def __call__(self, *args, **kw): + typ = args[self.param_index].__class__ + d = self.targets.get(typ) + if d is not None: + return d(*args, **kw) + else: + issub = issubclass + t = self.targets + ks = t.keys() + # ans = [t[k](*args, **kw) for k in ks if issub(typ, k)] + # if len(ans) == 1: + # return ans.pop() + ans = [k for k in ks if issub(typ, k)] + if len(ans) > 0: + return t[ans[0]](*args, **kw) + return ans + + def add_target(self, typ, target): + self.targets[typ] = target + + @staticmethod + def __argspec(fn): + # Support for Python 3 type hints requires inspect.getfullargspec + if hasattr(inspect, 'getfullargspec'): + return inspect.getfullargspec(fn) + else: + return inspect.getargspec(fn) diff --git a/tests/codegen/arith.cl b/tests/codegen/arith.cl index af5951cf..e87433e6 100755 --- a/tests/codegen/arith.cl +++ b/tests/codegen/arith.cl @@ -1,9 +1,3 @@ -(* - * A contribution from Anne Sheets (sheets@cory) - * - * Tests the arithmetic operations and various other things - *) - class A { var : Int <- 0; @@ -138,20 +132,6 @@ class E inherits D { }; -(* The following code is from atoi.cl in ~cs164/examples *) - -(* - The class A2I provides integer-to-string and string-to-integer -conversion routines. To use these routines, either inherit them -in the class where needed, have a dummy variable bound to -something of type A2I, or simpl write (new A2I).method(argument). -*) - - -(* - c2i Converts a 1-character string to an integer. Aborts - if the string is not "0" through "9" -*) class A2I { c2i(char : String) : Int { @@ -165,14 +145,11 @@ class A2I { 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 *) + { abort(); 0; } fi fi fi fi fi fi fi fi fi fi }; -(* - i2c is the inverse of c2i. -*) + i2c(i : Int) : String { if i = 0 then "0" else if i = 1 then "1" else @@ -188,14 +165,7 @@ class A2I { fi fi fi fi fi fi fi fi fi fi }; -(* - a2i converts an ASCII string into an integer. The empty string -is converted to 0. Signed and unsigned strings are handled. The -method aborts if the string does not represent an integer. Very -long strings of digits produce strange answers because of arithmetic -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 @@ -204,8 +174,7 @@ overflow. fi fi fi }; -(* a2i_aux converts the usigned portion of the string. As a - programming example, this method is written iteratively. *) + a2i_aux(s : String) : Int { @@ -226,17 +195,13 @@ overflow. ) }; -(* i2a converts an integer to a string. Positive and negative - numbers are handled correctly. *) i2a(i : Int) : String { if i = 0 then "0" else if 0 < i then i2a_aux(i) else "-".concat(i2a_aux(i * ~1)) fi fi - }; - -(* i2a_aux is an example using recursion. *) + }; i2a_aux(i : Int) : String { if i = 0 then "" else diff --git a/tests/codegen/hello_world.mips b/tests/codegen/hello_world.mips new file mode 100644 index 00000000..14d176cd --- /dev/null +++ b/tests/codegen/hello_world.mips @@ -0,0 +1,792 @@ +.data +Object: .word 20 +.word 0 +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Object" +Int: .word 20 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Int" +Bool: .word 20 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Bool" +String: .word 32 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.word length_10 +.word concat_7 +.word substr_32 +.asciiz "String" +IO: .word 36 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.word out_string_33 +.word out_int_34 +.word in_string_36 +.word in_int_38 +.asciiz "IO" +Main: .word 40 +.word IO +.word ctor_39 +.word abort_2 +.word type_name_4 +.word out_string_33 +.word out_int_34 +.word in_string_36 +.word in_int_38 +.word main +.asciiz "Main" +exception_1: .asciiz "Se esta realizando dispatch sobre valor void" +exception_2: .asciiz "Se esta realizando case sobre valor void" +exception_3: .asciiz "El tipo de la expresion case no concuerda con ninguna rama" +exception_4: .asciiz "Division por cero" +exception_5: .asciiz "Substring fuera de rango" +exception_6: .asciiz "Abort" +data_6: .asciiz "" +data_7: .asciiz "Hello, World. +" +buffer: .space 1024 +.globl main +.text +main: +j entry +# cil function Node +ctor_0: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -0 +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +abort_2: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILLoadNode +la $t1, exception_6 +sw $t1,-8($a3) + # CILPrintNodeStr +lw $t1, -8($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +type_name_4: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILTypeOfNode +# llegar hasta la inf_table +lw $t1, -4($a3) +lw $t2, 0($t1) +# guardarlo en destino +sw $t2,-8($a3) +# CILTypeName +lw $t1, -8($a3) +lw $t2, 0($t1) +add $t3, $t2, $t1 +sw $t3, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +concat_7: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -8 +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -12 +sw $t2, 0($t3) +# CILConcatNode +# Concat +lw $t1, -12($a3) +li $s0, 0 +whilel1_0: +lw $t0, -12($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, pawhilel2_4 +addi $s0,$s0,1 +j whilel1_0 +pawhilel2_4: +move $t7,$s0 +li $s0, 0 +whilel2_1: +lw $t0, -8($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, finl_8 +addi $s0, $s0,1 +j whilel2_1 +finl_8: +add $t7, $t7,$s0 +addi $t7, $t7, 1 +move $a0,$t7 +li $v0, 9 +syscall +li $s0, 0 +li $s1, 0 +move $t5, $v0 +# puntero en t5 +whilecopy1_5: +# puntero en a +lw $t0, -12($a3) +add $t0, $t0,$s0 +add $t4, $t5, $s0 +lb $t1, 0($t0) +beq $t1, $s1, pawhilecopy2_7 +addi $s0,$s0,1 +# move $a0,$s0 +# li $v0, 1 +# syscall +sb $t1, 0($t4) +j whilecopy1_5 +pawhilecopy2_7: +# move $a0,$s0 +# li $v0, 1 +# syscall +move $t7, $s0 +li $s0, 0 +whilecopy2_6: +# puntero en a2 +lw $t0, -8($a3) +add $t0, $t0,$s0 +add $t4, $t5, $t7 +lb $t1, 0($t0) +sb $t1, 0($t4) +beq $t1, $zero, fin_2 +addi $s0,$s0,1 +addi $t7,$t7,1 +j whilecopy2_6 +fin_2: +add $t4, $t5, $t7 +li $t1, 0 +lb $t1, 0($t4) +# li $v0, 4 +# move $a0, $t5 +# syscall +sw $t5, -16($a3) +# CILReturnNode +lw $t1, -16($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +length_10: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -8 +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -8 +sw $t2, 0($t3) + # Length +li $s0, 0 +while_9: +lw $t0, -8($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, fin_10 +addi $s0,$s0,1 +j while_9 +fin_10: +sw $s0, -12($a3) +# CILReturnNode +lw $t1, -12($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +substr_32: +addi $a3, $sp, 12 +# reservar locarvars +add $sp, $sp, -44 +# assign +li $t1, 0 +sw $t1, -16($a3) +# CILLessThan +lw $t1, -8($a3) +lw $t2, -16($a3) +slt $t3, $t1, $t2 +sw $t3, -20($a3) +# CILGotoIfNode +lw $t1, -20($a3) +bne $t1, $zero, label_type_14 +# CILLessThan +lw $t1, -12($a3) +lw $t2, -16($a3) +slt $t3, $t1, $t2 +sw $t3, -20($a3) +# CILGotoIfNode +lw $t1, -20($a3) +bne $t1, $zero, label_type_16 +# CILGotoIfNode +lw $t1, -12($a3) +bne $t1, $zero, label_type_11 +# CILGotoNode +j label_type_12 +# CILLabelNode +label_type_11: +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -24 +sw $t2, 0($t3) + # Length +li $s0, 0 +while_11: +lw $t0, -24($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, fin_12 +addi $s0,$s0,1 +j while_11 +fin_12: +sw $s0, -32($a3) +# CILPlusNode +lw $t2, -8($a3) +lw $t3, -12($a3) +add $t1, $t2, $t3 +sw $t1, -36($a3) +# CILMinusNode +lw $t2, -36($a3) +li $t3, 1 +sub $t1, $t2, $t3 +sw $t1, -36($a3) +# CILLessThan +lw $t1, -36($a3) +lw $t2, -32($a3) +slt $t3, $t1, $t2 +sw $t3, -28($a3) +# CILGotoIfNode +lw $t1, -28($a3) +bne $t1, $zero, label_type_24 +# CILGotoNode +j label_type_25 +# CILLabelNode +label_type_24: +# CILSubstringNode + # Substring +lw $s3, -24($a3) +lw $t1, -8($a3) +lw $t2, -12($a3) +add $s3, $s3, $t1 +addi $a0, $t2, 1 +li $v0, 9 +syscall +li $s0, 0 +while_13: +move $t4, $v0 +move $t0, $s3 +add $t0, $t0,$s0 +add $t4, $t4, $s0 +lb $t1, 0($t0) +sb $t1, 0($t4) +addi $s0,$s0,1 +beq $s0, $t2, fin_14 +j while_13 +fin_14: +addi $s0,$s0,1 +addi $t4, $t4, 1 +li $t5, 0 +lb $t5, 0($t4) +sw $v0, -40($a3) +# CILReturnNode +lw $t1, -40($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# CILGotoNode +j label_type_26 +# CILLabelNode +label_type_25: +# CILLoadNode +la $t1, exception_5 +sw $t1,-44($a3) + # CILPrintNodeStr +lw $t1, -44($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_26: +# CILGotoNode +j label_type_13 +# CILLabelNode +label_type_12: +# CILLoadNode +la $t1, data_6 +sw $t1,-48($a3) +# CILReturnNode +lw $t1, -48($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# CILLabelNode +label_type_13: +# CILGotoNode +j label_type_17 +# CILLabelNode +label_type_16: +# CILLoadNode +la $t1, exception_5 +sw $t1,-52($a3) + # CILPrintNodeStr +lw $t1, -52($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_17: +# CILGotoNode +j label_type_15 +# CILLabelNode +label_type_14: +# CILLoadNode +la $t1, exception_5 +sw $t1,-56($a3) + # CILPrintNodeStr +lw $t1, -56($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_15: +# cil function Node +out_string_33: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -0 + # CILPrintNodeStr +lw $t1, -8($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILReturnNode +lw $t1, -4($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +out_int_34: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -0 + # CILPrintNodeInt +lw $t1, -8($a3) +li $v0, 1 +move $a0, $t1 +syscall +# CILReturnNode +lw $t1, -4($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +in_string_36: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILReadStrNode + # leer string +li $s0,0 +li $s3, 10 +# coger tamanho y almacenar en buffer +while1_15: +la $t0, buffer +add $t0, $t0, $s0 +li $v0, 12 +syscall +addi $s0,$s0,1 +beq $v0, $s3, fin_17 +# beq $v0, $zero, error +# error +sb $v0, 0($t0) +j while1_15 +fin_17: +li $v0, 0 +sb $v0, 0($t0) +# reservar espacio +move $a0, $s0 +li $v0, 9 +syscall +# asignar espacio a t5 +move $t5, $v0 +li $s0,0 +li $s1,0 +li $s2,0 +# copiar de buffer pa t5 +while2_16: +la $t0, buffer +move $t1, $t5 +add $t0, $t0, $s0 +add $t1, $t1, $s1 +lb $t2, 0($t0) +sb $t2, 0($t1) +beq $t2, $s2, fin1_18 +addi $s0,$s0,1 +addi $s1,$s1,1 +j while2_16 +fin1_18: +sw $t5, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +in_int_38: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILReadNodeInt +li $v0, 5 +syscall +sw $v0, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +ctor_39: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_0 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +main: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -28 +# CILLoadNode +la $t1, data_7 +sw $t1,-16($a3) +# assign +lw $t1, -16($a3) +sw $t1, -12($a3) +# CILMinusNode +li $t2, 0 +lw $t3, -20($a3) +sub $t1, $t2, $t3 +sw $t1, -24($a3) +# CILGotoIfNode +lw $t1, -24($a3) +bne $t1, $zero, label_6 +# CILGotoNode +j label_7 +# CILLabelNode +label_6: +# CILTypeOfNode +# llegar hasta la inf_table +lw $t1, -20($a3) +lw $t2, 0($t1) +# guardarlo en destino +sw $t2,-28($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -20($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) +# CILParamNode +lw $t1, -12($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) +# CILDynamicCallNode +lw $t1, -28($a3) +lw $t2, 20($t1) +jalr $t2 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILGotoNode +j label_8 +# CILLabelNode +label_7: +# CILLoadNode +la $t1, exception_1 +sw $t1,-32($a3) + # CILPrintNodeStr +lw $t1, -32($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_8: +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +entry: +addi $a3, $sp, 0 +# reservar locarvars +add $sp, $sp, -8 +# CILAllocateNode +# reserva memoria +li $a0, 4 +li $v0, 9 +syscall + # guardar en dest +sw $v0, -4($a3) + # en la instancia poner referencia a su info_table +la $t1, Main +sw $t1, 0($v0) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_39 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal main +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnFinal +li $a0, 0 +li $v0, 17 +syscall diff --git a/tests/codegen/life.cl b/tests/codegen/life.cl index b83d9795..883c2eff 100755 --- a/tests/codegen/life.cl +++ b/tests/codegen/life.cl @@ -1,45 +1,4 @@ -(* The Game of Life - Tendo Kayiira, Summer '95 - With code taken from /private/cool/class/examples/cells.cl - - This introduction was taken off the internet. It gives a brief - description of the Game Of Life. It also gives the rules by which - this particular game follows. - - Introduction - - John Conway's Game of Life is a mathematical amusement, but it - is also much more: an insight into how a system of simple - cellualar automata can create complex, odd, and often aesthetically - pleasing patterns. It is played on a cartesian grid of cells - which are either 'on' or 'off' The game gets it's name from the - similarity between the behaviour of these cells and the behaviour - of living organisms. - - The Rules - - The playfield is a cartesian grid of arbitrary size. Each cell in - this grid can be in an 'on' state or an 'off' state. On each 'turn' - (called a generation,) the state of each cell changes simultaneously - depending on it's state and the state of all cells adjacent to it. - - For 'on' cells, - If the cell has 0 or 1 neighbours which are 'on', the cell turns - 'off'. ('dies of loneliness') - If the cell has 2 or 3 neighbours which are 'on', the cell stays - 'on'. (nothing happens to that cell) - If the cell has 4, 5, 6, 7, 8, or 9 neighbours which are 'on', - the cell turns 'off'. ('dies of overcrowding') - - For 'off' cells, - If the cell has 0, 1, 2, 4, 5, 6, 7, 8, or 9 neighbours which - are 'on', the cell stays 'off'. (nothing happens to that cell) - If the cell has 3 neighbours which are 'on', the cell turns - 'on'. (3 neighbouring 'alive' cells 'give birth' to a fourth.) - - Repeat for as many generations as desired. - - *) + class Board inherits IO { diff --git a/tests/codegen/mine.cl b/tests/codegen/mine.cl new file mode 100644 index 00000000..38b44590 --- /dev/null +++ b/tests/codegen/mine.cl @@ -0,0 +1,11 @@ +class A { }; +class B inherits A { }; +class C inherits B { }; +class D inherits B { }; + +class Main inherits IO { + main(): IO { out_string("Hello World!")}; + + test(a: A): B { a <- new C }; + test2(a: A): D { a <- new D }; +}; \ No newline at end of file diff --git a/tests/parser/case5.cl b/tests/parser/case5.cl index 51fea8a0..b36c663e 100644 --- a/tests/parser/case5.cl +++ b/tests/parser/case5.cl @@ -59,7 +59,7 @@ class Test { testing7(): Object { case test2 of - x: Int <- new IO.out_string("Es un entero!"); -- Must be '=>' not '<-' + x: Int <- new IO.out_string("Es un entero!"); -- Must be '=>' not '<-'; y: String => new IO.out_string("Es una cadena!"); z: Bool => new IO.out_string("Es un booleano!"); esac diff --git a/tests/semantic/arithmetic1.cl b/tests/semantic/arithmetic1.cl index bf94eb19..ac1e9798 100644 --- a/tests/semantic/arithmetic1.cl +++ b/tests/semantic/arithmetic1.cl @@ -1,11 +1,7 @@ --The static types of the two sub-expressions must be Int. -class A { }; -class B inherits A { }; -class C inherits B { }; - class Main inherits IO { main(): IO { out_string("Hello World!")}; - test: Int <- let x: Int <- 1 * 2 / 3 - 4 + new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() - in x <- x + new A.type_name().concat(new B.type_name().concat(new C.type_name())); -}; \ No newline at end of file + +}; + diff --git a/tests/semantic/arithmetic1.mips b/tests/semantic/arithmetic1.mips new file mode 100644 index 00000000..c1f35333 --- /dev/null +++ b/tests/semantic/arithmetic1.mips @@ -0,0 +1,783 @@ +.data +Object: .word 20 +.word 0 +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Object" +Int: .word 20 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Int" +Bool: .word 20 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Bool" +String: .word 32 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.word length_10 +.word concat_7 +.word substr_32 +.asciiz "String" +IO: .word 36 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.word out_string_33 +.word out_int_34 +.word in_string_36 +.word in_int_38 +.asciiz "IO" +Main: .word 40 +.word IO +.word ctor_39 +.word abort_2 +.word type_name_4 +.word out_string_33 +.word out_int_34 +.word in_string_36 +.word in_int_38 +.word func_main_0 +.asciiz "Main" +exception_1: .asciiz "Se esta realizando dispatch sobre valor void" +exception_2: .asciiz "Se esta realizando case sobre valor void" +exception_3: .asciiz "El tipo de la expresion case no concuerda con ninguna rama" +exception_4: .asciiz "Division por cero" +exception_5: .asciiz "Substring fuera de rango" +exception_6: .asciiz "Abort" +data_6: .asciiz "" +data_7: .asciiz "Hello World!" +buffer: .space 1024 +.globl main +.text +main: +j entry +# cil function Node +ctor_0: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -0 +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +abort_2: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILLoadNode +la $t1, exception_6 +sw $t1,-8($a3) + # CILPrintNodeStr +lw $t1, -8($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +type_name_4: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILTypeOfNode +# llegar hasta la inf_table +lw $t1, -4($a3) +lw $t2, 0($t1) +# guardarlo en destino +sw $t2,-8($a3) +# CILTypeName +lw $t1, -8($a3) +lw $t2, 0($t1) +add $t3, $t2, $t1 +sw $t3, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +concat_7: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -8 +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -12 +sw $t2, 0($t3) +# CILConcatNode +# Concat +lw $t1, -12($a3) +li $s0, 0 +whilel1_0: +lw $t0, -12($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, pawhilel2_4 +addi $s0,$s0,1 +j whilel1_0 +pawhilel2_4: +move $t7,$s0 +li $s0, 0 +whilel2_1: +lw $t0, -8($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, finl_8 +addi $s0, $s0,1 +j whilel2_1 +finl_8: +add $t7, $t7,$s0 +addi $t7, $t7, 1 +move $a0,$t7 +li $v0, 9 +syscall +li $s0, 0 +li $s1, 0 +move $t5, $v0 +# puntero en t5 +whilecopy1_5: +# puntero en a +lw $t0, -12($a3) +add $t0, $t0,$s0 +add $t4, $t5, $s0 +lb $t1, 0($t0) +beq $t1, $s1, pawhilecopy2_7 +addi $s0,$s0,1 +# move $a0,$s0 +# li $v0, 1 +# syscall +sb $t1, 0($t4) +j whilecopy1_5 +pawhilecopy2_7: +# move $a0,$s0 +# li $v0, 1 +# syscall +move $t7, $s0 +li $s0, 0 +whilecopy2_6: +# puntero en a2 +lw $t0, -8($a3) +add $t0, $t0,$s0 +add $t4, $t5, $t7 +lb $t1, 0($t0) +sb $t1, 0($t4) +beq $t1, $zero, fin_2 +addi $s0,$s0,1 +addi $t7,$t7,1 +j whilecopy2_6 +fin_2: +add $t4, $t5, $t7 +li $t1, 0 +lb $t1, 0($t4) +# li $v0, 4 +# move $a0, $t5 +# syscall +sw $t5, -16($a3) +# CILReturnNode +lw $t1, -16($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +length_10: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -8 +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -8 +sw $t2, 0($t3) + # Length +li $s0, 0 +while_9: +lw $t0, -8($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, fin_10 +addi $s0,$s0,1 +j while_9 +fin_10: +sw $s0, -12($a3) +# CILReturnNode +lw $t1, -12($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +substr_32: +addi $a3, $sp, 12 +# reservar locarvars +add $sp, $sp, -44 +# assign +li $t1, 0 +sw $t1, -16($a3) +# CILLessThan +lw $t1, -8($a3) +lw $t2, -16($a3) +slt $t3, $t1, $t2 +sw $t3, -20($a3) +# CILGotoIfNode +lw $t1, -20($a3) +bne $t1, $zero, label_type_14 +# CILLessThan +lw $t1, -12($a3) +lw $t2, -16($a3) +slt $t3, $t1, $t2 +sw $t3, -20($a3) +# CILGotoIfNode +lw $t1, -20($a3) +bne $t1, $zero, label_type_16 +# CILGotoIfNode +lw $t1, -12($a3) +bne $t1, $zero, label_type_11 +# CILGotoNode +j label_type_12 +# CILLabelNode +label_type_11: +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -24 +sw $t2, 0($t3) + # Length +li $s0, 0 +while_11: +lw $t0, -24($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, fin_12 +addi $s0,$s0,1 +j while_11 +fin_12: +sw $s0, -32($a3) +# CILPlusNode +lw $t2, -8($a3) +lw $t3, -12($a3) +add $t1, $t2, $t3 +sw $t1, -36($a3) +# CILMinusNode +lw $t2, -36($a3) +li $t3, 1 +sub $t1, $t2, $t3 +sw $t1, -36($a3) +# CILLessThan +lw $t1, -36($a3) +lw $t2, -32($a3) +slt $t3, $t1, $t2 +sw $t3, -28($a3) +# CILGotoIfNode +lw $t1, -28($a3) +bne $t1, $zero, label_type_24 +# CILGotoNode +j label_type_25 +# CILLabelNode +label_type_24: +# CILSubstringNode + # Substring +lw $s3, -24($a3) +lw $t1, -8($a3) +lw $t2, -12($a3) +add $s3, $s3, $t1 +addi $a0, $t2, 1 +li $v0, 9 +syscall +li $s0, 0 +while_13: +move $t4, $v0 +move $t0, $s3 +add $t0, $t0,$s0 +add $t4, $t4, $s0 +lb $t1, 0($t0) +sb $t1, 0($t4) +addi $s0,$s0,1 +beq $s0, $t2, fin_14 +j while_13 +fin_14: +addi $s0,$s0,1 +addi $t4, $t4, 1 +li $t5, 0 +lb $t5, 0($t4) +sw $v0, -40($a3) +# CILReturnNode +lw $t1, -40($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# CILGotoNode +j label_type_26 +# CILLabelNode +label_type_25: +# CILLoadNode +la $t1, exception_5 +sw $t1,-44($a3) + # CILPrintNodeStr +lw $t1, -44($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_26: +# CILGotoNode +j label_type_13 +# CILLabelNode +label_type_12: +# CILLoadNode +la $t1, data_6 +sw $t1,-48($a3) +# CILReturnNode +lw $t1, -48($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# CILLabelNode +label_type_13: +# CILGotoNode +j label_type_17 +# CILLabelNode +label_type_16: +# CILLoadNode +la $t1, exception_5 +sw $t1,-52($a3) + # CILPrintNodeStr +lw $t1, -52($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_17: +# CILGotoNode +j label_type_15 +# CILLabelNode +label_type_14: +# CILLoadNode +la $t1, exception_5 +sw $t1,-56($a3) + # CILPrintNodeStr +lw $t1, -56($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_15: +# cil function Node +out_string_33: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -0 + # CILPrintNodeStr +lw $t1, -8($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILReturnNode +lw $t1, -4($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +out_int_34: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -0 + # CILPrintNodeInt +lw $t1, -8($a3) +li $v0, 1 +move $a0, $t1 +syscall +# CILReturnNode +lw $t1, -4($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +in_string_36: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILReadStrNode + # leer string +li $s0,0 +li $s3, 10 +# coger tamanho y almacenar en buffer +while1_15: +la $t0, buffer +add $t0, $t0, $s0 +li $v0, 12 +syscall +addi $s0,$s0,1 +beq $v0, $s3, fin_17 +# beq $v0, $zero, error +# error +sb $v0, 0($t0) +j while1_15 +fin_17: +li $v0, 0 +sb $v0, 0($t0) +# reservar espacio +move $a0, $s0 +li $v0, 9 +syscall +# asignar espacio a t5 +move $t5, $v0 +li $s0,0 +li $s1,0 +li $s2,0 +# copiar de buffer pa t5 +while2_16: +la $t0, buffer +move $t1, $t5 +add $t0, $t0, $s0 +add $t1, $t1, $s1 +lb $t2, 0($t0) +sb $t2, 0($t1) +beq $t2, $s2, fin1_18 +addi $s0,$s0,1 +addi $s1,$s1,1 +j while2_16 +fin1_18: +sw $t5, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +in_int_38: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILReadNodeInt +li $v0, 5 +syscall +sw $v0, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +ctor_39: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_0 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +func_main_0: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -20 +# CILMinusNode +li $t2, 0 +lw $t3, -4($a3) +sub $t1, $t2, $t3 +sw $t1, -12($a3) +# CILGotoIfNode +lw $t1, -12($a3) +bne $t1, $zero, label_3 +# CILGotoNode +j label_4 +# CILLabelNode +label_3: +# CILLoadNode +la $t1, data_7 +sw $t1,-20($a3) +# assign +lw $t1, -20($a3) +sw $t1, -16($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) +# CILParamNode +lw $t1, -16($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal out_string_33 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILGotoNode +j label_5 +# CILLabelNode +label_4: +# CILLoadNode +la $t1, exception_1 +sw $t1,-24($a3) + # CILPrintNodeStr +lw $t1, -24($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_5: +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +entry: +addi $a3, $sp, 0 +# reservar locarvars +add $sp, $sp, -8 +# CILAllocateNode +# reserva memoria +li $a0, 4 +li $v0, 9 +syscall + # guardar en dest +sw $v0, -4($a3) + # en la instancia poner referencia a su info_table +la $t1, Main +sw $t1, 0($v0) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_39 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal func_main_0 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnFinal +li $a0, 0 +li $v0, 17 +syscall diff --git a/tests/semantic/arithmetic8.cl b/tests/semantic/arithmetic8.cl index 3210bdb8..aa30f8fe 100644 --- a/tests/semantic/arithmetic8.cl +++ b/tests/semantic/arithmetic8.cl @@ -6,7 +6,7 @@ class C inherits B { }; class Main inherits IO { main(): IO { out_string("Hello World!")}; - test: Int <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() + test: Bool <- let x: Bool <- 1 / 2 - 3 + 4 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length() in 1 < new A.type_name().concat(new B.type_name().concat(new C.type_name())).length(); }; diff --git a/tests/semantic/arithmetic8.mips b/tests/semantic/arithmetic8.mips new file mode 100644 index 00000000..ae446449 --- /dev/null +++ b/tests/semantic/arithmetic8.mips @@ -0,0 +1,1097 @@ +.data +Object: .word 20 +.word 0 +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Object" +Int: .word 20 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Int" +Bool: .word 20 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.asciiz "Bool" +String: .word 32 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.word length_10 +.word concat_7 +.word substr_32 +.asciiz "String" +IO: .word 36 +.word Object +.word ctor_0 +.word abort_2 +.word type_name_4 +.word out_string_33 +.word out_int_34 +.word in_string_36 +.word in_int_38 +.asciiz "IO" +A: .word 20 +.word Object +.word ctor_39 +.word abort_2 +.word type_name_4 +.asciiz "A" +B: .word 20 +.word A +.word ctor_40 +.word abort_2 +.word type_name_4 +.asciiz "B" +C: .word 20 +.word B +.word ctor_41 +.word abort_2 +.word type_name_4 +.asciiz "C" +Main: .word 40 +.word IO +.word ctor_42 +.word abort_2 +.word type_name_4 +.word out_string_33 +.word out_int_34 +.word in_string_36 +.word in_int_38 +.word main +.asciiz "Main" +exception_1: .asciiz "Se esta realizando dispatch sobre valor void" +exception_2: .asciiz "Se esta realizando case sobre valor void" +exception_3: .asciiz "El tipo de la expresion case no concuerda con ninguna rama" +exception_4: .asciiz "Division por cero" +exception_5: .asciiz "Substring fuera de rango" +exception_6: .asciiz "Abort" +data_6: .asciiz "" +data_7: .asciiz "Hello World!" +buffer: .space 1024 +.globl main +.text +main: +j entry +# cil function Node +ctor_0: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -0 +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +abort_2: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILLoadNode +la $t1, exception_6 +sw $t1,-8($a3) + # CILPrintNodeStr +lw $t1, -8($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +type_name_4: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILTypeOfNode +# llegar hasta la inf_table +lw $t1, -4($a3) +lw $t2, 0($t1) +# guardarlo en destino +sw $t2,-8($a3) +# CILTypeName +lw $t1, -8($a3) +lw $t2, 0($t1) +add $t3, $t2, $t1 +sw $t3, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +concat_7: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -8 +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -12 +sw $t2, 0($t3) +# CILConcatNode +# Concat +lw $t1, -12($a3) +li $s0, 0 +whilel1_0: +lw $t0, -12($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, pawhilel2_4 +addi $s0,$s0,1 +j whilel1_0 +pawhilel2_4: +move $t7,$s0 +li $s0, 0 +whilel2_1: +lw $t0, -8($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, finl_8 +addi $s0, $s0,1 +j whilel2_1 +finl_8: +add $t7, $t7,$s0 +addi $t7, $t7, 1 +move $a0,$t7 +li $v0, 9 +syscall +li $s0, 0 +li $s1, 0 +move $t5, $v0 +# puntero en t5 +whilecopy1_5: +# puntero en a +lw $t0, -12($a3) +add $t0, $t0,$s0 +add $t4, $t5, $s0 +lb $t1, 0($t0) +beq $t1, $s1, pawhilecopy2_7 +addi $s0,$s0,1 +# move $a0,$s0 +# li $v0, 1 +# syscall +sb $t1, 0($t4) +j whilecopy1_5 +pawhilecopy2_7: +# move $a0,$s0 +# li $v0, 1 +# syscall +move $t7, $s0 +li $s0, 0 +whilecopy2_6: +# puntero en a2 +lw $t0, -8($a3) +add $t0, $t0,$s0 +add $t4, $t5, $t7 +lb $t1, 0($t0) +sb $t1, 0($t4) +beq $t1, $zero, fin_2 +addi $s0,$s0,1 +addi $t7,$t7,1 +j whilecopy2_6 +fin_2: +add $t4, $t5, $t7 +li $t1, 0 +lb $t1, 0($t4) +# li $v0, 4 +# move $a0, $t5 +# syscall +sw $t5, -16($a3) +# CILReturnNode +lw $t1, -16($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +length_10: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -8 +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -8 +sw $t2, 0($t3) + # Length +li $s0, 0 +while_9: +lw $t0, -8($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, fin_10 +addi $s0,$s0,1 +j while_9 +fin_10: +sw $s0, -12($a3) +# CILReturnNode +lw $t1, -12($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +substr_32: +addi $a3, $sp, 12 +# reservar locarvars +add $sp, $sp, -44 +# assign +li $t1, 0 +sw $t1, -16($a3) +# CILLessThan +lw $t1, -8($a3) +lw $t2, -16($a3) +slt $t3, $t1, $t2 +sw $t3, -20($a3) +# CILGotoIfNode +lw $t1, -20($a3) +bne $t1, $zero, label_type_14 +# CILLessThan +lw $t1, -12($a3) +lw $t2, -16($a3) +slt $t3, $t1, $t2 +sw $t3, -20($a3) +# CILGotoIfNode +lw $t1, -20($a3) +bne $t1, $zero, label_type_16 +# CILGotoIfNode +lw $t1, -12($a3) +bne $t1, $zero, label_type_11 +# CILGotoNode +j label_type_12 +# CILLabelNode +label_type_11: +# CILGetAttribNode +lw $t1, -4($a3) +lw $t2, 4($t1) +addi $t3, $a3, -24 +sw $t2, 0($t3) + # Length +li $s0, 0 +while_11: +lw $t0, -24($a3) +add $t0, $t0,$s0 +lb $t1, 0($t0) +beq $t1, $zero, fin_12 +addi $s0,$s0,1 +j while_11 +fin_12: +sw $s0, -32($a3) +# CILPlusNode +lw $t2, -8($a3) +lw $t3, -12($a3) +add $t1, $t2, $t3 +sw $t1, -36($a3) +# CILMinusNode +lw $t2, -36($a3) +li $t3, 1 +sub $t1, $t2, $t3 +sw $t1, -36($a3) +# CILLessThan +lw $t1, -36($a3) +lw $t2, -32($a3) +slt $t3, $t1, $t2 +sw $t3, -28($a3) +# CILGotoIfNode +lw $t1, -28($a3) +bne $t1, $zero, label_type_24 +# CILGotoNode +j label_type_25 +# CILLabelNode +label_type_24: +# CILSubstringNode + # Substring +lw $s3, -24($a3) +lw $t1, -8($a3) +lw $t2, -12($a3) +add $s3, $s3, $t1 +addi $a0, $t2, 1 +li $v0, 9 +syscall +li $s0, 0 +while_13: +move $t4, $v0 +move $t0, $s3 +add $t0, $t0,$s0 +add $t4, $t4, $s0 +lb $t1, 0($t0) +sb $t1, 0($t4) +addi $s0,$s0,1 +beq $s0, $t2, fin_14 +j while_13 +fin_14: +addi $s0,$s0,1 +addi $t4, $t4, 1 +li $t5, 0 +lb $t5, 0($t4) +sw $v0, -40($a3) +# CILReturnNode +lw $t1, -40($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# CILGotoNode +j label_type_26 +# CILLabelNode +label_type_25: +# CILLoadNode +la $t1, exception_5 +sw $t1,-44($a3) + # CILPrintNodeStr +lw $t1, -44($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_26: +# CILGotoNode +j label_type_13 +# CILLabelNode +label_type_12: +# CILLoadNode +la $t1, data_6 +sw $t1,-48($a3) +# CILReturnNode +lw $t1, -48($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# CILLabelNode +label_type_13: +# CILGotoNode +j label_type_17 +# CILLabelNode +label_type_16: +# CILLoadNode +la $t1, exception_5 +sw $t1,-52($a3) + # CILPrintNodeStr +lw $t1, -52($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_17: +# CILGotoNode +j label_type_15 +# CILLabelNode +label_type_14: +# CILLoadNode +la $t1, exception_5 +sw $t1,-56($a3) + # CILPrintNodeStr +lw $t1, -56($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_type_15: +# cil function Node +out_string_33: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -0 + # CILPrintNodeStr +lw $t1, -8($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILReturnNode +lw $t1, -4($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +out_int_34: +addi $a3, $sp, 8 +# reservar locarvars +add $sp, $sp, -0 + # CILPrintNodeInt +lw $t1, -8($a3) +li $v0, 1 +move $a0, $t1 +syscall +# CILReturnNode +lw $t1, -4($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +in_string_36: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILReadStrNode + # leer string +li $s0,0 +li $s3, 10 +# coger tamanho y almacenar en buffer +while1_15: +la $t0, buffer +add $t0, $t0, $s0 +li $v0, 12 +syscall +addi $s0,$s0,1 +beq $v0, $s3, fin_17 +# beq $v0, $zero, error +# error +sb $v0, 0($t0) +j while1_15 +fin_17: +li $v0, 0 +sb $v0, 0($t0) +# reservar espacio +move $a0, $s0 +li $v0, 9 +syscall +# asignar espacio a t5 +move $t5, $v0 +li $s0,0 +li $s1,0 +li $s2,0 +# copiar de buffer pa t5 +while2_16: +la $t0, buffer +move $t1, $t5 +add $t0, $t0, $s0 +add $t1, $t1, $s1 +lb $t2, 0($t0) +sb $t2, 0($t1) +beq $t2, $s2, fin1_18 +addi $s0,$s0,1 +addi $s1,$s1,1 +j while2_16 +fin1_18: +sw $t5, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +in_int_38: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 +# CILReadNodeInt +li $v0, 5 +syscall +sw $v0, -8($a3) +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +ctor_39: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_0 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +ctor_40: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_39 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +ctor_41: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_40 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +ctor_42: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -4 + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_0 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnNode +li $v1, 0 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# cil function Node +main: +addi $a3, $sp, 4 +# reservar locarvars +add $sp, $sp, -64 +# CILLoadNode +la $t1, data_7 +sw $t1,-16($a3) +# assign +lw $t1, -16($a3) +sw $t1, -12($a3) +# CILMinusNode +li $t2, 0 +lw $t3, -20($a3) +sub $t1, $t2, $t3 +sw $t1, -24($a3) +# CILGotoIfNode +lw $t1, -24($a3) +bne $t1, $zero, label_9 +# CILGotoNode +j label_10 +# CILLabelNode +label_9: +# CILTypeOfNode +# llegar hasta la inf_table +lw $t1, -20($a3) +lw $t2, 0($t1) +# guardarlo en destino +sw $t2,-28($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -20($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) +# CILParamNode +lw $t1, -12($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) +# CILDynamicCallNode +lw $t1, -28($a3) +lw $t2, 20($t1) +jalr $t2 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILGotoNode +j label_11 +# CILLabelNode +label_10: +# CILLoadNode +la $t1, exception_1 +sw $t1,-32($a3) + # CILPrintNodeStr +lw $t1, -32($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_11: +# CILReturnNode +lw $t1, -8($a3) +move $v1, $t1 +# restaurar pila con respecto al metodo +move $sp, $a3 +jr $ra +# assign +lw $t1, -40($a3) +sw $t1, -36($a3) +# assign +li $t1, 1 +sw $t1, -44($a3) +# CILMinusNode +li $t2, 0 +lw $t3, -52($a3) +sub $t1, $t2, $t3 +sw $t1, -56($a3) +# CILGotoIfNode +lw $t1, -56($a3) +bne $t1, $zero, label_19 +# CILGotoNode +j label_20 +# CILLabelNode +label_19: +# CILTypeOfNode +# llegar hasta la inf_table +lw $t1, -52($a3) +lw $t2, 0($t1) +# guardarlo en destino +sw $t2,-60($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -52($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) +# CILDynamicCallNode +lw $t1, -60($a3) +lw $t2, 20($t1) +jalr $t2 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -48($a3) +# CILGotoNode +j label_21 +# CILLabelNode +label_20: +# CILLoadNode +la $t1, exception_1 +sw $t1,-64($a3) + # CILPrintNodeStr +lw $t1, -64($a3) +li $v0, 4 +move $a0, $t1 +syscall +# CILErrorNode +li $a0, 1 +li $v0, 17 +syscall +# CILLabelNode +label_21: +# CILLessThan +lw $t1, -44($a3) +lw $t2, -48($a3) +slt $t3, $t1, $t2 +sw $t3, -36($a3) +# CILSetAttribNode +lw $t1, -4($a3) +addi $t2, $t1, 4 +lw $t3, -36($a3) +sw $t3, 0($t2) +# cil function Node +entry: +addi $a3, $sp, 0 +# reservar locarvars +add $sp, $sp, -8 +# CILAllocateNode +# reserva memoria +li $a0, 8 +li $v0, 9 +syscall + # guardar en dest +sw $v0, -4($a3) + # en la instancia poner referencia a su info_table +la $t1, Main +sw $t1, 0($v0) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal ctor_42 +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) + # SaveState +# Salva registros +addi $sp, $sp, -76 +sw $t1, 0($sp) +sw $t2, 4($sp) +sw $t3, 8($sp) +sw $t4, 12($sp) +sw $t5, 16($sp) +sw $t6, 20($sp) +sw $t7, 24($sp) +sw $a0, 28($sp) +sw $a1, 32($sp) +sw $a2, 36($sp) +sw $a3, 40($sp) +sw $ra, 44($sp) +sw $s1, 48($sp) +sw $s2, 52($sp) +sw $s3, 56($sp) +sw $s4, 60($sp) +sw $s5, 64($sp) +sw $s6, 68($sp) +sw $s7, 72($sp) +# CILParamNode +lw $t1, -4($a3) +# push +addi $sp, $sp, -4 +sw $t1, 0($sp) + # CILStaticCallNode +jal main +# Carga registros +lw $t1, 0($sp) +lw $t2, 4($sp) +lw $t3, 8($sp) +lw $t4, 12($sp) +lw $t5, 16($sp) +lw $t6, 20($sp) +lw $t7, 24($sp) +lw $a0, 28($sp) +lw $a1, 32($sp) +lw $a2, 36($sp) +lw $a3, 40($sp) +lw $ra, 44($sp) +lw $s1, 48($sp) +lw $s2, 52($sp) +lw $s3, 56($sp) +lw $s4, 60($sp) +lw $s5, 64($sp) +lw $s6, 68($sp) +lw $s7, 72($sp) +addi $sp, $sp, 76 +sw $v1, -8($a3) +# CILReturnFinal +li $a0, 0 +li $v0, 17 +syscall diff --git a/tests/semantic/dispatch6.cl b/tests/semantic/dispatch6.cl index fcc033f2..77d353dd 100644 --- a/tests/semantic/dispatch6.cl +++ b/tests/semantic/dispatch6.cl @@ -1,8 +1,4 @@ -(* -e@B.f() invokes the method -f in class B on the object that is the value of e. For this form of dispatch, the static type to the left of -“@”must conform to the type specified to the right of “@”. -*) + class A { f(x: Int, y: Int): Int { x + y }; diff --git a/tests/semantic/inheritance3.cl b/tests/semantic/inheritance3.cl index 83a4e132..1d190aeb 100755 --- a/tests/semantic/inheritance3.cl +++ b/tests/semantic/inheritance3.cl @@ -6,8 +6,10 @@ class Main inherits IO { main: IO <- out_string("bye!"); }; -class A inherits A { +class A inherits A{ x: Int <- 3; - x(): String { ":)" }; -}; \ No newline at end of file +}; + + +