def visitExpr(self, ctx: DecafParser.ExprContext):
        #1. if expression contains location then check symbol table (global scope) for identifier
        if ctx.location():
            id = ctx.location().ID().getText()
            #2. if identifier not in symbol table then report error
            if (self.st.lookup(id) == None):
                print("Error: Found on line", ctx.start.line, ": ID(", id,
                      ") not declared before use.")
        #hint ctx.location() returns None if not part of expression
        #hint ctx.location() returns location rule context (e.g. ctx.location().ID().getText() gets identifier name)

        return self.visitChildren(ctx)
Example #2
0
    def visitExpr(self, ctx: DecafParser.ExprContext):
        if ctx.literal():
            int_literal = ctx.getText()
            self.body += 'movq $' + int_literal + ', %rax\n'
        elif ctx.location():
            loc_name = ctx.getText()
            location = self.st.lookup(loc_name)
            addr = str(location.getAddr())

            if location.mem == HEAP:
                self.body += 'movq ' + addr + '(%rbp), %rax\n'
            else:
                self.body += 'movq ' + addr + '(%rsp), %rax\n'
        else:
            self.visitChildren(ctx)
    def visitExpr(self, ctx: DecafParser.ExprContext): 
        if ctx.expr():
            #Rule 12 check that expr is type int for arith or rel op and check if exists in table before comparing
            if ctx.ADD() or ctx.MODULOS() or ctx.MINUS() or ctx.MULTIPLY() or ctx.DIVISION() or ctx.GREATER() or ctx.GREATEREQUALS or ctx.LESS() or ctx.LESSEQUALS():
                for index, _ in enumerate(ctx.expr()):
                    id = ctx.expr(index).getText()
                    check = self.st.lookup(id)
                    if check != 'int' and id.isdigit() != True and check == None: 
                        print("[Rule 12] error doesn't have type int for: (", id, ") on line:", ctx.start.line)                
            
            #Rule 14 check that logical and cond op have type boolean, if not None check symbol table else return error
            if ctx.NOT():
                temp = ctx.expr(0).getText().replace('!','')
                lookup = self.st.lookup(temp)
                if lookup == None or lookup.type != 'boolean':
                    print("[Rule 14] error type boolean not found for not expression, on line:", ctx.start.line)
            if ctx.ANDAND() or ctx.OROR():        
                temp = ctx.expr(0).getText().replace('!','')
                temp1 = ctx.expr(1).getText().replace('!','')
                lookup = self.st.lookup(temp)
                lookup1 = self.st.lookup(temp1)
                if lookup == None and lookup1 == None or lookup.type != 'boolean' and lookup1.type != 'boolean' :
                    print("[Rule 14] error type boolean not found for not expression, on line:", ctx.start.line)

            #Rule 13 check that eq op have type boolean or int, if not None check symbol table else return error
            if ctx.EQUALSEQUALS() or ctx.NOTEQUAL():         
                temp = ctx.expr(0).getText()
                temp1 = ctx.expr(1).getText()
                lookup = self.st.lookup(temp)
                lookup1 = self.st.lookup(temp1)
                if lookup != None and lookup1 != None and lookup.type != lookup1.type or lookup == None and lookup1 == None:
                    print("[Rule 13] error operands type do not match, on line:", ctx.start.line)
            
        # rule 2, No identifier is used before it is declared, check if it exists in the symbol table, this rule was provided by Ryan via screencast on moodle
        if ctx.location():
            id = ctx.location().ID().getText()
            if (self.st.lookup(id) == None):
                print("[Rule 2] error on line", ctx.start.line,'ID: (', id, ') not declared before use')     
        return self.visitChildren(ctx)
Example #4
0
    def visitExpr(self, ctx: DecafParser.ExprContext):
        line_num = ctx.start.line
        expr_type = ""

        if len(ctx.expr()) == 2:

            type_a = self.visit(ctx.expr(0))
            type_b = self.visit(ctx.expr(1))
            op = ctx.bin_op()

            if type_a == type_b:
                expr_type = type_a

            else:
                expr_type = None
                #print('Error on line', line_num, 'type mismatched in expression')

            #12
            if (op.rel_op() != None or op.arith_op() != None
                ) and type_a != 'int' and type_b != 'int':
                print('Error on line ' + str(line_num) +
                      ' operands must be of type int')
            #13
            elif op.eq_op() != None and type_a != type_b:
                print('Error on line ' + str(line_num) +
                      ' operands must be of same type')
            #14
            elif op.cond_op() != None and (type_a != 'boolean'
                                           or type_b != 'boolean'):
                print('Error on line ' + str(line_num) +
                      ' operands must be of type boolean')

        elif ctx.location() != None:

            var_name = ctx.location().ID().getText()
            var_symbol = self.st.lookup(var_name)

            if var_symbol != None:
                expr_type = var_symbol.type

            else:
                #2
                expr_type = None
                print('Error on line ' + str(line_num) + ', ' + var_name +
                      ' has not been declared')

        elif ctx.data_literal() != None:

            if ctx.data_literal().int_literal() != None:
                expr_type = 'int'

            elif ctx.data_literal().bool_literal() != None:
                expr_type = 'boolean'

            else:
                expr_type = None

        elif ctx.method_call() != None:

            method_name = ctx.method_call().method_name().getText()
            method_symbol = self.st.lookup(method_name)

            if method_symbol != None:

                expr_type = method_symbol.type
                self.visit(ctx.method_call())

            else:
                method_symbol = None

        elif ctx.EXCLAMATION() != None:

            expr_type = self.visit(ctx.expr(0))

            #14
            if expr_type != 'boolean':
                print('Error on line ' + str(line_num) +
                      ' operand must be of type boolean')

        else:
            self.visitChildren(ctx)

        return expr_type
    def visitExpr(self, ctx: DecafParser.ExprContext):
        line_number = ctx.start.line
        method_call = ctx.method_call()
        bin_oper = ""

        if ctx.expr(0) != None:
            if ctx.expr(0).bin_op() != None:
                bin_oper = ctx.expr(0).bin_op().getText()
        if self.eq_op:
            pass
        else:
            expressions = ctx.expr(0)
            if expressions != None:
                if ctx.expr(0).location() and bin_oper != None:
                    for items in ctx.expr():
                        locatons = items.getText()
                        """
                        check that the operands of bin_op are ints
                        """
                        if self.st.lookup(locatons).type != "int":
                            print(
                                "ERROR: can only use a airthmetic operation on ints",
                                line_number)
                if ctx.expr(0) and bin_oper != None:
                    if ctx.expr(0).location:
                        pass
                    else:
                        airth_op = ctx.expr(0).bin_op().airth_op().getText()
                        if airth_op in expressions.getText():
                            operands = ctx.expr(0).getText().replace(
                                airth_op, "")
                            listOfoperands = list(operands)
                            """
                            if operands are not loctions (meaning not varibles), try to chnage the 
                            type to int, if that fails throw error
                            """
                            for i in range(len(listOfoperands)):
                                try:
                                    int(listOfoperands[i])
                                except:
                                    print(
                                        "ERROR: can only use a airthmetic operation on ints",
                                        line_number)
        """
        check if a method call in side of an expression is not void as it must be a type to 
        be evaluated to something for it to be used in an expression, void is anon type
        """
        method_expr_params = []
        if method_call != None:
            method_params = method_call.expr()
            if self.st.lookup(method_call.ID().getText()).type == "void":
                print(
                    "ERROR: for method to be used here, method must return something"
                    + " line numnber", line_number)
                if "()" in method_call.getText():
                    name = method_call.getText()
                    name = name.replace("()", "")

                    for names in method_params:
                        method_expr_params = method_expr_params.append[names]
                    if len(method_expr_params) < len(
                            self.st.lookup(name).params):
                        print(
                            "ERROR: " + "method " +
                            self.st.lookup(name).id + " epecting",
                            len(self.st.lookup(name).params), "but got",
                            len(method_expr_params), "on line", line_number)

        return self.visitChildren(ctx)
    def visitExpr(self, ctx:DecafParser.ExprContext):

        # Expression is a variable.
        if ctx.location():
            var_name = ctx.location().getText()
            var_symbol = self.st.lookup(var_name)
            if "[" in var_name:
                split_var = var_name.split('[', 1)[0]
                var_symbol = self.st.lookup(split_var)
            if var_symbol == None:
                print('[Error]: Variable', var_name, 'has not been declared. Found on line', ctx.start.line)
            else:
                var_addr = var_symbol.getAddr()
                self.body += '\tmovq -' + str(var_addr[0]) + '(%rsp), %rax\n'

        # Expression is a literal (number or string/char)
        elif ctx.literal():
            number = ctx.literal().getText()
            if number == 'false':
                number = '0'
            if number == 'true':
                number = '1'
            self.body += '\tmovq $' + number + ', %rax\n'

        # Expression length is more than 1 (more expressions present such as an operation)
        elif len(ctx.expr()) > 1:
            # Visit the first expression.
            self.visit(ctx.expr(0))

            # Move stack pointer 1 place and save value of first expression.
            self.st.stack_pointer[-1] += 8
            self.body += '\tmovq %rax, ' + str(-self.st.stack_pointer[-1]) + '(%rsp)\n'

            # Visit the second expression.
            self.visit(ctx.expr(1))
            self.body += '\tmovq ' + str(-self.st.stack_pointer[-1]) + '(%rsp), %r10\n'
            self.st.stack_pointer[-1] -= 8
            self.body += '\tmovq %rax, %r11\n'

            # If a binary operator is present, check the operator and add appropriate code.
            if ctx.BIN_OP():
                if str(ctx.BIN_OP()) == '+':
                    self.body += '\taddq %r10, %r11\n'
                if str(ctx.BIN_OP()) == '*':
                    self.body += '\timul %r10, %r11\n'
                if str(ctx.BIN_OP()) == '-':
                    self.body += '\tsubq %r10, %r11\n'
                if str(ctx.BIN_OP()) == '/':
                    self.body += '\tmovq $0, rdx\n'
                    self.body += '\tmovq %r11, rbx\n'
                    self.body += '\tmovq %r10, rax\n'
                    self.body += '\tidiv %rbx\n'

            self.body += '\tmovq %r11, %rax\n'
Example #7
0
    def visitExpr(self, ctx:DecafParser.ExprContext):
                
        if ctx.data_literal():
            if ctx.data_literal().int_literal() != None:
                int_literal = ctx.data_literal().getText()
                self.body += 'movq $' + int_literal + ', %rax\n'
            
        elif ctx.location():
            loc_name = ctx.location().getText()
            location = self.st.lookup(loc_name)

            addr = location.getAddr()

            if location.mem == HEAP:
                self.body += 'movq ' + str(addr) + '(%rbp), %rax\n'
            else:
                self.body += 'movq ' + str(addr) + '(%rsp), %rax\n'

        elif len(ctx.expr()) == 2:
            self.visit(ctx.expr(0))
            self.body += 'movq %rax, %r10\n'

            self.st.stack_pointer[-1] += 8
            self.body += 'movq %r10, ' + str(-self.st.stack_pointer[-1]) + '(%rsp)\n'

            self.visit(ctx.expr(1))
            self.body += 'movq %rax, %r11\n'

            self.body += 'movq ' + str(-self.st.stack_pointer[-1]) + '(%rsp), %r10\n'
            self.st.stack_pointer[-1] -= 8

            if ctx.bin_op().arith_op().ADD():
                self.body += 'addq %r10, %r11\n'
            elif ctx.bin_op().arith_op().SUB():
                self.body += 'subq %r11, %r10\n'
                self.body += 'movq %r10, %r11\n'
            elif ctx.bin_op().arith_op().MUL():
                self.body += 'imul %r10, %r11\n'
            elif ctx.bin_op().arith_op().DIV():
                self.body += 'movq $0, %rdx\n'
                self.body += 'movq %r11, %rbx\n'
                self.body += 'movq %r10, %rax\n'
                self.body += 'idiv %rbx\n'
                self.body += 'movq %rax, %r11\n'

            self.body += 'movq %r11, %rax\n'

        else:
            self.visitChildren(ctx)