Ejemplo n.º 1
0
    def make_il(self, il_code, symbol_table, c):
        """ Make code for this node """
        symbol_table.new_scope()
        if self.first:
            self.first.make_il(il_code, symbol_table, c)

        start = il_code.get_label()
        cont = il_code.get_label()
        end = il_code.get_label()
        c = c.set_continue(cont).set_break(end)

        il_code.add(control_cmds.Label(start))
        with report_err():
            if self.second:
                cond = self.second.make_il(il_code, symbol_table, c)
                il_code.add(control_cmds.JumpZero(cond, end))

        with report_err():
            self.stat.make_il(il_code, symbol_table, c)

        il_code.add(control_cmds.Label(cont))

        with report_err():
            if self.third:
                self.third.make_il(il_code, symbol_table, c)

        il_code.add(control_cmds.Jump(start))
        il_code.add(control_cmds.Label(end))

        symbol_table.end_scope()
Ejemplo n.º 2
0
    def nonarith(self, left, right, il_code):
        """ Check equality of non-arithmetic expressions """

        # If either operand is a null pointer constant, cast it to the other's pointer type.
        if left.ctype.is_pointer() and right.null_ptr_const:
            right = set_type(right, left.ctype, il_code)
        elif right.ctype.is_pointer() and left.null_ptr_const:
            left = set_type(left, right.ctype, il_code)

        # If both operands are not pointer types, quit now
        if not left.ctype.is_pointer() or not right.ctype.is_pointer():
            with report_err():
                err = "comparison between incomparable types"
                raise CompilerError(err, self.op.r)

        # If one side is pointer to void, cast the other to same.
        elif left.ctype.arg.is_void():
            check_cast(right, left.ctype, self.op.r)
            right = set_type(right, left.ctype, il_code)
        elif right.ctype.arg.is_void():
            check_cast(left, right.ctype, self.op.r)
            left = set_type(left, right.ctype, il_code)

        # If both types are still incompatible, warn!
        elif not left.ctype.compatible(right.ctype):
            with report_err():
                err = "comparison between distinct pointer types"
                raise CompilerError(err, self.op.r)

        # Now, we can do comparison
        out = ILValue(ctypes.integer)
        il_code.add(self.eq_il_cmd(out, left, right))
        return out
Ejemplo n.º 3
0
    def parse_struct_spec(self, node, redec):
        """Parse struct ctype from the given decl_nodes.Struct node.

            node (decl_nodes.Struct) - the Struct node to parse
            redec (bool) - Whether this declaration is alone like so:
               struct S;

        or declares variables/has storage specifiers:
               struct S *p;
               extern struct S;

        If it's the first, then this is always a forward declaration for a new `struct S` but if it's the second and a
        `struct S` already exists in higher scope, it's just using the higher scope struct.
        """
        has_members = node.members is not None

        ctype_req = StructCType

        if node.tag:
            tag = str(node.tag)
            ctype = self.symbol_table.lookup_struct(tag)

            if ctype and not isinstance(ctype, ctype_req):
                err = f"defined as wrong kind of tag '{node.kind} {tag}'"
                raise CompilerError(err, node.r)

            if not ctype or has_members or redec:
                ctype = self.symbol_table.add_struct(tag, ctype_req(tag))

            if has_members and ctype.is_complete():
                err = f"redefinition of '{node.kind} {tag}'"
                raise CompilerError(err, node.r)

        else:
            ctype = ctype_req(None)

        if not has_members:
            return ctype

        # Struct does have members
        members = []
        members_set = set()
        for member in node.members:
            decl_infos = []  # needed in case get_decl_infos below fails
            with report_err():
                decl_infos = self.get_decl_infos(member)

            for decl_info in decl_infos:
                with report_err():
                    self.check_struct_member_decl_info(decl_info, node.kind,
                                                       members_set)

                    name = decl_info.identifier.content
                    members_set.add(name)
                    members.append((name, decl_info.ctype))

        ctype.set_members(members)
        return ctype
Ejemplo n.º 4
0
    def make_il(self, il_code, symbol_table, c):
        """ Make code for this declaration """

        self.set_self_vars(il_code, symbol_table, c)
        decl_infos = self.get_decl_infos(self.node)
        for info in decl_infos:
            with report_err():
                info.process(il_code, symbol_table, c)
Ejemplo n.º 5
0
    def make_il(self, il_code, symbol_table, c):
        """ Make code for this node """
        start = il_code.get_label()
        end = il_code.get_label()

        il_code.add(control_cmds.Label(start))
        c = c.set_continue(start).set_break(end)

        with report_err():
            self.stat.make_il(il_code, symbol_table, c)

        with report_err():
            cond = self.cond.make_il(il_code, symbol_table, c)
            il_code.add(control_cmds.JumpZero(cond, end))

        il_code.add(control_cmds.Jump(start))
        il_code.add(control_cmds.Label(end))
Ejemplo n.º 6
0
 def make_il(self, il_code, symbol_table, c):
     """ Make IL code for returning this value """
     label = self.get_label(c)
     if label:
         il_code.add(control_cmds.Jump(label))
     else:
         with report_err():
             err = f"{self.descr} statement not in loop"
             raise CompilerError(err, self.r)
Ejemplo n.º 7
0
    def make_il(self, il_code, symbol_table, c):
        """ Make code for this if statement """

        endif_label = il_code.get_label()
        with report_err():
            cond = self.cond.make_il(il_code, symbol_table, c)
            il_code.add(control_cmds.JumpZero(cond, endif_label))

        with report_err():
            self.stat.make_il(il_code, symbol_table, c)

        if self.else_stat:
            end_label = il_code.get_label()
            il_code.add(control_cmds.Jump(end_label))
            il_code.add(control_cmds.Label(endif_label))
            with report_err():
                self.else_stat.make_il(il_code, symbol_table, c)
            il_code.add(control_cmds.Label(end_label))
        else:
            il_code.add(control_cmds.Label(endif_label))
Ejemplo n.º 8
0
    def make_il(self, il_code, symbol_table, c, no_scope=False):
        """Make IL code for every block item, in order. If no_scope is True, then don`t create a new symbol table scope.
        Used by function definition so that parameters can live in the scope of the function body.
        """
        if not no_scope:
            symbol_table.new_scope()

        c = c.set_global(False)
        for item in self.items:
            with report_err():
                item.make_il(il_code, symbol_table, c)

        if not no_scope:
            symbol_table.end_scope()
Ejemplo n.º 9
0
    def get_decl_infos(self, node):
        """Given a node, returns a list of decl_info objects for that node."""
        any_dec = bool(node.decls)
        base_type, storage = self.make_specs_ctype(node.specs, any_dec)

        out = []
        for decl, init in zip(node.decls, node.inits):
            with report_err():
                ctype, identifier = self.make_ctype(decl, base_type)

                if ctype.is_function():
                    param_identifiers = self.extract_params(decl)
                else:
                    param_identifiers = []

                out.append(
                    DeclInfo(identifier, ctype, decl.r, storage, init,
                             self.body, param_identifiers))

        return out
Ejemplo n.º 10
0
 def make_il(self, il_code, symbol_table, c):
     """ Make code for the root """
     for node in self.nodes:
         with report_err():
             c = c.set_global(True)
             node.make_il(il_code, symbol_table, c)