Exemplo 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()
Exemplo n.º 2
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()
Exemplo n.º 3
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
Exemplo n.º 4
0
    def make_il(self, il_code, symbol_table, c):
        """Make code for this declaration."""

        decl_infos = self.get_decl_infos(self.node, symbol_table)
        for info in decl_infos:
            with report_err():
                self.process(info, il_code, symbol_table, c)
Exemplo 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():
            cond = self.cond.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.Jump(start))
        il_code.add(control_cmds.Label(end))
Exemplo n.º 6
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)
Exemplo n.º 7
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():
            cond = self.cond.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.Jump(start))
        il_code.add(control_cmds.Label(end))
Exemplo n.º 8
0
 def make_il(self, il_code, symbol_table, c):
     """Make IL code for every block item, in order."""
     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)
     symbol_table.end_scope()
Exemplo n.º 9
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.descrip} statement not in loop"
             raise CompilerError(err, self.r)
Exemplo n.º 10
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.descrip} statement not in loop"
             raise CompilerError(err, self.r)
Exemplo n.º 11
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))
Exemplo n.º 12
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))
Exemplo n.º 13
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 getattr(right.literal, "val", None) == 0):
            right = set_type(right, left.ctype, il_code)
        elif (right.ctype.is_pointer()
              and getattr(left.literal, "val", None) == 0):
            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
Exemplo n.º 14
0
    def get_decl_infos(self, node, symbol_table):
        """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, symbol_table)

        proc = zip(node.decls, node.ranges, node.inits)

        out = []
        for decl, range, init in proc:
            with report_err():
                ctype, identifier = self.make_ctype(
                    decl, base_type, symbol_table)

                out.append(DeclInfo(identifier, ctype, range, storage, init))

        return out
Exemplo n.º 15
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 do not 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()
Exemplo n.º 16
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 do not 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()
Exemplo n.º 17
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
Exemplo n.º 18
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
Exemplo n.º 19
0
    def parse_struct_union_spec(self, node, redec):
        """Parse struct or union ctype from the given decl_nodes.Struct node.

        node (decl_nodes.Struct/Union) - the Struct or Union node to parse
        redec (bool) - Whether this declaration is alone like so:

           struct S;
           union U;

        or declares variables/has storage specifiers:

           struct S *p;
           extern struct S;
           union U *u;
           extern union U;

        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

        if node.kind == token_kinds.struct_kw:
            ctype_req = StructCType
        else:
            ctype_req = UnionCType

        if node.tag:
            tag = str(node.tag)
            ctype = self.symbol_table.lookup_struct_union(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_union(tag, ctype_req(tag))

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

        else:  # anonymous struct/union
            ctype = ctype_req(None)

        if not has_members:
            return ctype

        # Struct or union 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
Exemplo n.º 20
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)
Exemplo n.º 21
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)
Exemplo n.º 22
0
    def parse_struct_union_spec(self, node, redec):
        """Parse struct or union ctype from the given decl_nodes.Struct node.

        node (decl_nodes.Struct/Union) - the Struct or Union node to parse
        redec (bool) - Whether this declaration is alone like so:

           struct S;
           union U;

        or declares variables/has storage specifiers:

           struct S *p;
           extern struct S;
           union U *u;
           extern union U;

        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

        if node.kind == token_kinds.struct_kw:
            ctype_req = StructCType
        else:
            ctype_req = UnionCType

        if node.tag:
            tag = str(node.tag)
            ctype = self.symbol_table.lookup_struct_union(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_union(tag, ctype_req(tag))

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

        else:  # anonymous struct/union
            ctype = ctype_req(None)

        if not has_members:
            return ctype

        # Struct or union 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
Exemplo n.º 23
0
    def parse_struct_spec(self, node, redec, symbol_table):
        """Parse a 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
        if node.tag:
            tag = str(node.tag)
            ctype = symbol_table.lookup_struct(tag)

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

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

        else:
            ctype = StructCType(None)

        if not has_members:
            return ctype

        # Struct does have members
        members = []
        member_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, symbol_table)

            for decl_info in decl_infos:
                with report_err():
                    if decl_info.identifier is None:
                        # someone snuck an abstract declarator into here!
                        err = "missing name of struct member"
                        raise CompilerError(err, decl_info.range)

                    if decl_info.storage is not None:
                        err = "cannot have storage specifier on struct member"
                        raise CompilerError(err, decl_info.range)

                    if decl_info.ctype.is_function():
                        err = "cannot have function type as struct member"
                        raise CompilerError(err, decl_info.range)

                    # TODO: 6.7.2.1.18 (allow flexible array members)
                    if not decl_info.ctype.is_complete():
                        err = "cannot have incomplete type as struct member"
                        raise CompilerError(err, decl_info.range)

                    # TODO: 6.7.2.1.13 (anonymous structs)
                    attr = decl_info.identifier.content

                    if attr in member_set:
                        err = f"duplicate member '{attr}'"
                        raise CompilerError(err, decl_info.identifier.r)

                    members.append((attr, decl_info.ctype))
                    member_set.add(attr)

        ctype.set_members(members)
        return ctype