def visit(self, node: cil.PlusNode): """ assuming left and right operands are ints """ left_offset = self.get_address(node.left) right_offset = self.get_address(node.right) dest_offset = self.get_address(node.dest) self.add_inst( mips.CommentNode(f"<plus:{node.dest}<-{node.left}+{node.right}>"), mips.LWNode(t0, (left_offset, fp)).with_comm(f"Load Int {node.left}"), mips.LWNode(t0, (4, t0)).with_comm('Load Int_value at offset 4'), mips.LWNode( t1, (right_offset, fp)).with_comm(f"Load Int {node.right}"), mips.LWNode(t1, (4, t1)).with_comm('Load Int_value at offset 4'), mips.ADDNode(t2, t0, t1).with_comm('Add the integer values'), ) self.visit(cil.StaticCallNode('Int__init', node.dest)) self.add_inst( mips.LWNode(t1, (dest_offset, fp)), mips.SWNode(t2, 4, t1), mips.CommentNode(f"</plus:{node.dest}<-{node.left}+{node.right}>"), )
def visit(self, node: cil.ConformsNode): left_offset = self.get_address(node.left) # right_offset = self.get_address(node.right) dest_offset = self.get_address(node.dest) self.add_inst( mips.CommentNode( f"<conforms:{node.dest}<-{node.left}-{node.right}>"), ) self.add_inst( mips.LWNode( t0, (left_offset, fp)).with_comm("Load left pointer to self"), mips.LWNode( a0, (0, t0)).with_comm("Load left pointer to type of self"), mips.LANode(a1, node.right), mips.JALNode('conforms'), mips.MoveNode(s0, v0)) self.visit(cil.StaticCallNode('Bool__init', node.dest)) self.add_inst( mips.LWNode(t0, (dest_offset, fp)), mips.SWNode(s0, 4, t0), mips.CommentNode( f"</conforms:{node.dest}<-{node.left}-{node.right}>"), )
def visit(self, node: cil.SubstringNode): self.add_inst( mips.CommentNode( f"<substr:>{node.dest}[{node.index}:{node.length}]")) self.visit(cil.StaticCallNode('String__init', node.dest)) src_address = self.get_address('self') dest_address = self.get_address(node.dest) index_address = self.get_address(node.index) length_address = self.get_address(node.length) push_src = (mips.LWNode(a0, (src_address, fp)), mips.LWNode(a0, (4, a0))) push_length = (mips.LWNode(a2, (length_address, fp)), mips.LWNode(a2, (4, a2))) push_index = (mips.LWNode(a1, (index_address, fp)), mips.LWNode(a1, (4, a1))) self.add_inst( *push_src, *push_length, *push_index, mips.JALNode('substr'), ) self.add_inst( mips.LWNode(t1, (dest_address, fp)), mips.SWNode(v0, 4, t1), mips.CommentNode( f"</substr:>{node.dest}[{node.index}:{node.length}]"))
def visit(self, node: ast.IntegerNode, scope: Scope): value = self.visit(int(node.lex), scope) int_instance = self.add_local('int_instance') self.add_inst(cil.StaticCallNode('Int__init', int_instance)) attr_index = self.root.get_type('Int').attributes.index('Int_value') attr_at = cil.AttributeAt('Int_value', attr_index) self.add_inst(cil.SetAttrNode(int_instance, attr_at, value)) return int_instance
def visit(self, node: ast.BooleanNode, scope: Scope): value = self.visit(node.lex == 'true', scope) bool_instance = self.add_local('bool_instance') self.add_inst(cil.StaticCallNode('Bool__init', bool_instance)) attr_index = self.root.get_type('Bool').attributes.index('Bool_value') attr_at = cil.AttributeAt('Bool_Value', attr_index) self.add_inst(cil.SetAttrNode(bool_instance, attr_at, value)) return bool_instance
def visit(self, node: cil.ReadIntNode): address = self.get_address(node.dest) self.add_inst(mips.CommentNode(f"<readint:{node.dest}>"), mips.LINode(v0, 5), mips.SysCallNode(), mips.MoveNode(t2, v0)) self.visit(cil.StaticCallNode("Int__init", node.dest)) self.add_inst(mips.LWNode(t1, (address, fp)), mips.SWNode(t2, 4, t1), mips.LWNode(v0, (address, fp)), mips.CommentNode(f"</readint:{node.dest}>"))
def visit(self, node: ast.StringNode, scope: Scope): self.add_comment('Instantiating string: ' + (node.lex if len(node.lex) < 20 else node.lex[:15] + '...')) value = self.visit(node.lex, scope) str_instance = self.add_local('str_instance') self.add_inst(cil.StaticCallNode('String__init', str_instance)) attr_index = self.root.get_type('String').attributes.index( 'String_value') attr_at = cil.AttributeAt('String_value', attr_index) self.add_inst(cil.SetAttrNode(str_instance, attr_at, value)) return str_instance
def visit(self, node: cil.NegationNode): src_offset = self.get_address(node.src) dest_offset = self.get_address(node.dest) self.add_inst(mips.CommentNode(f"<negate:{node.dest}<-~{node.src}>"), mips.LWNode(t0, (src_offset, fp)), mips.LWNode(t0, (4, t0)), mips.XORINode(t1, t0, 1)) self.visit(cil.StaticCallNode('Bool__init', node.dest)) self.add_inst( mips.LWNode(t0, (dest_offset, fp)), mips.SWNode(t1, 4, t0), mips.CommentNode(f"</negate:{node.dest}<-~{node.src}>"), )
def visit(self, node: cil.IsVoidNode): src = self.get_address(node.src) dest = self.get_address(node.dest) self.add_inst(mips.CommentNode(f"<isvoid:{node.dest}-{node.src}>"), ) self.visit(cil.StaticCallNode('Bool__init', node.dest)) self.add_inst( mips.LWNode(a0, (src, fp)).with_comm('Push instance pointer'), mips.JALNode('isvoid'), mips.LWNode(t0, (dest, fp)).with_comm('Load Bool pointer'), mips.SWNode(v0, 4, t0).with_comm('Save isvoid result as value of Bool'), mips.CommentNode(f"</isvoid:{node.dest}-{node.src}>"), )
def visit(self, node: cil.ComplementNode): src = self.get_address(node.src) dest = self.get_address(node.dest) self.add_inst(mips.CommentNode(f"</complement:{node.dest}>"), ) self.visit(cil.StaticCallNode('Int__init', node.dest)) self.add_inst( mips.LWNode(t0, (src, fp)), mips.LWNode(t0, (4, t0)), mips.NOTNode(t0, t0), mips.ADDINode(t0, t0, 1), mips.LWNode(t1, (dest, fp)), mips.SWNode(t0, 4, t1), mips.CommentNode(f"</complement:{node.dest}>"), )
def visit(self, node: cil.TypeNameNode): name_offset = self.types['Object'].name_offset src_offset = self.get_address(node.src) self.add_inst(mips.CommentNode(f"<typename:{node.dest}-{node.src}>"), ) self.visit(cil.StaticCallNode('String__init', node.dest)) self.add_inst( mips.LWNode(t0, (src_offset, fp)).with_comm('Load pointer to self'), mips.LWNode(t0, (0, t0)).with_comm('Load pointer to type of self'), mips.ADDINode(t0, t0, name_offset).with_comm('Point to name of type'), mips.SWNode( t0, 4, v0).with_comm('Save name of the type in the new string'), mips.CommentNode(f"</typename:{node.dest}-{node.src}>"), )
def visit(self, node: cil.LengthNode): self.add_inst( mips.CommentNode(f"<length:{node.dest}=len({node.src})>")) self.visit(cil.StaticCallNode("Int__init", node.dest)) src_address = self.get_address(node.src) dest_address = self.get_address(node.dest) self.add_inst( mips.LWNode(a0, (src_address, fp)), mips.LWNode(a0, (4, a0)), mips.JALNode('length'), mips.LWNode(t1, (dest_address, fp)), mips.SWNode(v0, 4, t1), ) self.add_inst( mips.CommentNode(f"</length:{node.dest}=len({node.src})>"))
def visit(self, node: cil.ReadStringNode): self.add_inst(mips.CommentNode(f"<readstring:{node.dest}>")) address = self.get_address(node.dest) self.add_inst(mips.LINode(a0, 512), mips.JALNode('malloc'), mips.MoveNode(t2, v0)) self.add_inst( mips.MoveNode(a0, t2), mips.LINode(a1, 512), mips.LINode(v0, 8), mips.SysCallNode(), ) self.visit(cil.StaticCallNode('String__init', node.dest)) self.add_inst(mips.LWNode(t0, (address, fp)), mips.SWNode(t2, 4, t0)) # Remove eol self.add_inst(mips.MoveNode(a0, t2), mips.JALNode('remove_eol')) self.add_inst(mips.CommentNode(f"</readstring:{node.dest}>"))
def visit(self, node: cil.EqualNode): left = self.get_address(node.left) right = self.get_address(node.right) dest = self.get_address(node.dest) self.add_inst( mips.CommentNode( f"<equal: {node.dest} <- {node.left} = {node.right}>"), ) self.visit(cil.StaticCallNode("Bool__init", node.dest)) self.add_inst( mips.LWNode(a0, (left, fp)), mips.LWNode(a1, (right, fp)), mips.JALNode("equal"), mips.LWNode(t0, (dest, fp)), mips.SWNode(v0, 4, t0), mips.CommentNode( f"<equal: {node.dest} <- {node.left} = {node.right}>"), )
def visit(self, node: cil.StarNode): left_offset = self.get_address(node.left) right_offset = self.get_address(node.right) dest_offset = self.get_address(node.dest) self.add_inst( mips.CommentNode(f"<star:{node.dest}<-{node.left}-{node.right}>"), mips.LWNode(t0, (left_offset, fp)), # load Int_value at offset 4 mips.LWNode(t0, (4, t0)), mips.LWNode(t1, (right_offset, fp)), # load Int_value at offset 4 mips.LWNode(t1, (4, t1)), mips.MULTNode(t2, t0, t1), # multiply the integer values ) self.visit(cil.StaticCallNode('Int__init', node.dest)) self.add_inst( mips.LWNode(t1, (dest_offset, fp)), mips.SWNode(t2, 4, t1), mips.CommentNode(f"</star:{node.dest}<-{node.left}-{node.right}>"), )
def visit(self, node: cil.ConcatNode): self.add_inst( mips.CommentNode(f"<concat:{node.dest}={node.str1}+{node.str2}>")) self.visit(cil.StaticCallNode("String__init", node.dest)) str1_address = self.get_address(node.str1) str2_address = self.get_address(node.str2) dest_address = self.get_address(node.dest) # Calc length of str1 and save it in t0 length_of_str1 = (mips.LWNode(a0, (str1_address, fp)), mips.LWNode(a0, (4, a0)), mips.JALNode('length'), mips.MoveNode(t0, v0)) # Calc length of str2 and save it in t1 length_of_str2 = (mips.LWNode(a0, (str2_address, fp)), mips.LWNode(a0, (4, a0)), mips.JALNode('length'), mips.MoveNode(t1, v0)) push_str1 = (mips.LWNode(a0, (str1_address, fp)), mips.LWNode(a0, (4, a0))) push_str2 = (mips.LWNode(a1, (str2_address, fp)), mips.LWNode(a1, (4, a1))) push_length = (mips.ADDNode(a2, t0, t1), ) self.add_inst( *length_of_str1, *length_of_str2, *push_str1, *push_str2, *push_length, mips.JALNode('concat'), ) self.add_inst(mips.LWNode(t1, (dest_address, fp)), mips.SWNode(v0, 4, t1)) self.add_inst( mips.CommentNode(f"</concat:{node.dest}={node.str1}+{node.str2}>"))
def visit(self, node: ast.InstantiateNode, scope: Scope): if node.lex == 'String': return self.visit(ast.StringNode('""'), scope) elif node.lex == 'Bool': return self.visit(ast.BooleanNode('false'), scope) elif node.lex == 'Int': return self.visit(ast.IntegerNode('0'), scope) self.add_comment(f'Instantiating type {node.lex}') # type_node = self.root.get_type(node.lex) # attr_values = [] # for attr in type_node.attributes: # attr_expr = type_node.get_attr_node(attr) # attr_values.append(self.visit(attr_expr, scope)) instance = self.add_local(f'inst_of_{node.lex}') self.add_inst(cil.StaticCallNode(f'{node.lex}__init', instance)) # for attr, attr_value in zip(type_node.attributes, attr_values): # attr_index = type_node.attributes.index(attr) # attr_at = cil.AttributeAt(attr, attr_index) # self.add_inst( # cil.SetAttrNode(instance, attr_at, attr_value) # ) return instance
def visit(self, node: ast.ProgramNode, scope: Scope): # the root scope stores void to avoid semantic errors initializing # the void attribute of classes to void. After that every function # has access to void through that attribute in every class. # So, pop it to avoid repeated locals. scope.locals.pop(0) # build the code functions for class_ in node.declarations: tagged_scope = scope.get_tagged_scope(class_.id) self.visit(class_, deepcopy(tagged_scope)) # build the entry function: for class_ in node.declarations: if class_.id == 'Main': for feature in class_.features: if isinstance(feature, ast.FuncDeclarationNode ) and feature.id == 'main': self.add_function('main') instance = self.add_local('main_instance') self.add_inst( cil.StaticCallNode('Main__init', instance)) self.add_comment('Calling main') result = self.add_local('result') self.add_inst(cil.ArgNode(instance)) self.add_inst( cil.DynamicCallNode(instance, 'main', result, None, 'Main')) self.add_inst(cil.ReturnNode(0)) break # add the default functions of COOL # TODO: add missing instructions self.code += [ cil.FunctionNode(name='Object__init', params=[], local_vars=[ cil.LocalNode('self'), ], instructions=[ cil.InitNode('self', 'Object'), cil.ReturnNode('self') ]), cil.FunctionNode( name='Object_abort', params=[cil.ParamNode('self'), cil.ParamNode('typename')], local_vars=[], instructions=[ cil.AbortNode(), cil.ReturnNode(), ]), cil.FunctionNode(name='Object_type_name', params=[ cil.ParamNode('self'), ], local_vars=[ cil.LocalNode('name'), ], instructions=[ cil.TypeNameNode('name', 'self'), cil.ReturnNode('name'), ]), cil.FunctionNode(name='Object_copy', params=[ cil.ParamNode('self'), ], local_vars=[ cil.LocalNode('self_copy'), ], instructions=[ cil.AssignNode('self_copy', 'self'), cil.ReturnNode('self_copy'), ]), cil.FunctionNode(name='IO__init', params=[], local_vars=[ cil.LocalNode('self'), ], instructions=[ cil.InitNode('self', 'IO'), cil.ReturnNode('self'), ]), cil.FunctionNode(name='IO_out_string', params=[ cil.ParamNode('self'), cil.ParamNode('str_addr'), ], local_vars=[], instructions=[ cil.PrintStringNode('str_addr'), cil.ReturnNode('self'), ]), cil.FunctionNode(name='IO_out_int', params=[ cil.ParamNode('self'), cil.ParamNode('int_addr'), ], local_vars=[], instructions=[ cil.PrintIntNode('int_addr'), cil.ReturnNode('self'), ]), cil.FunctionNode(name='IO_in_string', params=[ cil.ParamNode('self'), ], local_vars=[ cil.LocalNode('_in_string'), ], instructions=[ cil.ReadStringNode('_in_string'), cil.ReturnNode('_in_string'), ]), cil.FunctionNode(name='IO_in_int', params=[ cil.ParamNode('self'), ], local_vars=[ cil.LocalNode('_in_int'), ], instructions=[ cil.ReadIntNode('_in_int'), cil.ReturnNode('_in_int'), ]), cil.FunctionNode(name='String__init', params=[], local_vars=[ cil.LocalNode('self'), ], instructions=[ cil.InitNode('self', 'String'), cil.ReturnNode('self'), ]), cil.FunctionNode(name='String_length', params=[ cil.ParamNode('self'), ], local_vars=[ cil.LocalNode('_length'), ], instructions=[ cil.LengthNode('self', '_length'), cil.ReturnNode('_length'), ]), cil.FunctionNode(name='String_concat', params=[ cil.ParamNode('self'), cil.ParamNode('other_str'), ], local_vars=[ cil.LocalNode('result'), ], instructions=[ cil.ConcatNode('result', 'self', 'other_str'), cil.ReturnNode('result'), ]), cil.FunctionNode(name='String_substr', params=[ cil.ParamNode('self'), cil.ParamNode('index'), cil.ParamNode('length'), ], local_vars=[ cil.LocalNode('result'), ], instructions=[ cil.SubstringNode('result', 'value', 'index', 'length'), cil.ReturnNode('result'), ]), cil.FunctionNode(name='Bool__init', params=[], local_vars=[ cil.LocalNode('self'), ], instructions=[ cil.InitNode('self', 'Bool'), cil.ReturnNode('self'), ]), cil.FunctionNode(name='Int__init', params=[], local_vars=[ cil.LocalNode('self'), ], instructions=[ cil.InitNode('self', 'Int'), cil.ReturnNode('self'), ]), cil.FunctionNode(name='Void__init', params=[], local_vars=[ cil.LocalNode('self'), ], instructions=[ cil.InitNode('self', 'Void'), cil.ReturnNode('self'), ]), ]