예제 #1
0
def type_check_relational(node1, node2, op, token, is_bool=False):
    allowed_class = {'BasicType'}
    allowed_base = {'int', 'long', 'char', 'double', 'float'}
    if node1.type == "error" or node2.type == "error":
        return Node(type="error")
    if node1.type.class_type not in allowed_class or node2.type.class_type not in allowed_class:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")
    if is_bool:
        if node1.type.type == "bool" and node2.type.type == "bool":
            return Node(name="binary_op",
                        value="bool" + op,
                        children=[node1, node2],
                        type=BasicType('bool'))
    if node1.type.type not in allowed_base or node2.type.type not in allowed_base:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")

    node1, node2, typ = implicit_casting(node1, node2)
    return Node(name="binary_op",
                value=typ.stype + op,
                children=[node1, node2],
                type=BasicType('bool'))
예제 #2
0
def type_check_logical(node1, node2, op, token):
    allowed_class = {'BasicType'}
    allowed_base = {'int', 'long', 'char', 'double', 'float', 'bool'}
    if node1.type == "error" or node2.type == "error":
        return Node(type="error")
    if node1.type.class_type not in allowed_class or node2.type.class_type not in allowed_class:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")
    if node1.type.type not in allowed_base or node2.type.type not in allowed_base:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")

    if node1.type.type != "bool":
        node1 = Node(name="type_cast",
                     value='bool',
                     children=[node1],
                     type=BasicType('bool'))
    if node2.type.type != "bool":
        node2 = Node(name="type_cast",
                     value='bool',
                     children=[node2],
                     type=BasicType('bool'))
    return Node(name="binary_op",
                value=op,
                children=[node1, node2],
                type=BasicType('bool'))
예제 #3
0
def typecast(node1, type, token=None, hard=False):
    node1 = load_place(node1)
    assert isinstance(type, Type), "not of class Type"
    assert type.class_type in {"BasicType", "PointerType",
                               "StructType"}, "not valid type"
    # assert node1.type.class_type in {"BasicType","PointerType"}, "not valid type"
    # assert "sconst@" not in node1.place, "string in typecast"
    if node1.type.stype == type.stype:
        if hard: node1.type = type
        return node1
    elif "sconst@" in node1.place:
        # print(str(node1.type.stype),str(type.stype))
        if token:
            Errors(errorType='TypeError',
                   errorText="cannot assign string constant to type " +
                   type.stype,
                   token_object=token)
            return Node(type="error")
        else:
            assert "string in typecast"
    else:
        node = Node(name="type_cast",
                    value=type.stype,
                    children=[node1],
                    type=type)
        node.code = node1.code
        node.place = node1.place
        if type.class_type == 'PointerType':
            type1 = 'long'
        else:
            type1 = type.type
        if node1.type.class_type == 'PointerType':
            type2 = 'long'
        else:
            type2 = node1.type.type

        if type1 == type2:
            return node
        if type1 in {"long", "int"} and type2 in {"long", "int"}:
            return node
        if "const@" in node1.place:
            node.place = get_const(const=get_const_value(node1.place),
                                   type=BasicType(type1))
            return node
        node.place = get_newtmp(type=BasicType(type1))
        node.code += [
            gen(op=type2 + "_to_" + type1,
                place1=node1.place,
                place3=node.place,
                code=node.place + " = " + type2 + "_to_" + type1 + " " +
                node1.place)
        ]
    return node
예제 #4
0
def p_type_specifier(p):
    '''
    type_specifier : VOID
                   | CHAR
                   | INT
                   | LONG
                   | FLOAT
                   | DOUBLE
                   | STRUCT IDENTIFIER
                   | ENUM IDENTIFIER
                   | BOOL
    '''
    if p[1] == 'enum':
        pass
    elif p[1] == 'struct':
        success = sym_table.look_up_struct(name=p[2], token_object=p.slice[-1])
        if success:
            p[0] = Node(type=success)
        else:
            p[0] = Node(type="error")
    else:
        if p[1] == 'void':
            p[0] = Node(type=Type())
        else:
            p[0] = Node(type=BasicType(type=p[1]))

    assert isinstance(p[0], Node), "return object is not Node"
    assert p[0].type == 'error' or isinstance(
        p[0].type, Type), "unexpected type attribute of return object"
예제 #5
0
def p_conditional_expression(p):
    '''
    conditional_expression : logical_or_expression
	                       | logical_or_expression QUES_MARK expression COLON conditional_expression
    '''

    if len(p) == 2:
        p[0] = p[1]
    else:
        if p[1].type == "error" or p[3].type == "error" or p[5].type == "error":
            p[0] = Node(type="error")
            return
        allowed_class = {'BasicType'}
        allowed_base = {'int', 'long', 'char', 'bool', 'double', 'float'}
        if p[1].type.class_type not in allowed_class or p[
                1].type.type not in allowed_base:
            Errors(errorType='TypeError',
                   errorText=p[2] + ' not support type ' + p[1].type.stype,
                   token_object=p.slice[2])
            p[0] = Node(type="error")
            return
        if p[3].type != p[5].type:
            Errors(errorType='TypeError',
                   errorText='type should be same',
                   token_object=p.slice[2])
            p[0] = Node(type="error")
        p[1] = Node(name="type_cast",
                    value='bool',
                    children=[p[1]],
                    type=BasicType('bool'))
        p[0] = Node("ternary_op", children=[p[1], p[3], p[5]], type=p[3].type)
예제 #6
0
def const_use(place, sconst=False):
    if "sconst@" in place:
        if sconst and place not in alloc.keys():
            string = remove_backslash(place.split("@")[-1])
            # print(string,len(string))
            node_type = PointerType(type=BasicType("char"),
                                    array_size=[len(string) + 1],
                                    array_type=BasicType("char"))
            sym_table._add_entry(name=place, type=node_type)
            alloc[place] = string
        return
    if place not in alloc.keys():
        node_type = BasicType("long") if place[0] == "l" else BasicType(
            "float")
        sym_table._add_entry(name=place, type=node_type)
        alloc[place] = get_const_value(place)
예제 #7
0
def get_newtmp(type=BasicType("long")):
    assert isinstance(type, Type), "inconsistent type for newtmp"
    global temp_cnt
    name = "tmp@" + str(temp_cnt)
    temp_cnt += 1
    sym_table.add_entry(name=name, type=type)
    temp_dict[name] = sym_table.curr_symbol_table
    return name
예제 #8
0
def type_check_relational(node1, node2, op, token):
    allowed_class = {'BasicType', 'PointerType'}
    allowed_base = {'int', 'long', 'char', 'float', 'bool'}
    if node1.type == "error" or node2.type == "error":
        return Node(type="error")
    if "sconst@" in node1.place or "sconst@" in node2.place:
        Errors(errorType='TypeError',
               errorText=op + ' not support string constant',
               token_object=token)
        return Node(type="error")
    if node1.type.class_type not in allowed_class or node2.type.class_type not in allowed_class:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")
    if node1.type.class_type == "PointerType":
        node1.type = BasicType("long")
    if node2.type.class_type == "PointerType":
        node2.type = BasicType("long")
    if node1.type.type not in allowed_base or node2.type.type not in allowed_base:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")

    node1, node2, typ = implicit_casting(node1, node2)
    node = Node(name="binary_op",
                value=typ.stype + op,
                children=[node1, node2],
                type=BasicType('bool'))
    node.code = node1.code + node2.code
    tmp, code = get_opcode(op=typ.stype + op,
                           place1=node1.place,
                           place2=node2.place,
                           type=BasicType('bool'))
    node.code += [code]
    node.place = tmp
    return node
예제 #9
0
def p_primary_expression(p):
    '''
    primary_expression : IDENTIFIER
                       | INT_CONSTANT
                       | HEX_CONSTANT
                       | OCTAL_CONSTANT
                       | EXPONENT_CONSTANT
                       | REAL_CONSTANT
                       | CHAR_CONSTANT
                       | STR_CONSTANT
                       | L_PAREN expression R_PAREN
                       | TRUE
                       | FALSE
                       | NULL
    '''
    if len(p) == 2:
        if p.slice[-1].type == "IDENTIFIER":
            #looking for id
            success = sym_table.look_up(name=p[1], token_object=p.slice[-1])
            if success:
                p[0] = Node(name="id", value=p[1], type=success.type)
            else:
                p[0] = Node(name="id", type='error')
            return

        if p.slice[-1].type in [
                "INT_CONSTANT", "HEX_CONSTANT", "OCTAL_CONSTANT"
        ]:
            p[0] = Node(name="constant", value=p[1], type=BasicType('int'))

        elif p.slice[-1].type in ["EXPONENT_CONSTANT", "REAL_CONSTANT"]:
            p[0] = Node(name="constant", value=p[1], type=BasicType('float'))

        elif p.slice[-1].type == "CHAR_CONSTANT":
            p[0] = Node(name="constant", value=p[1], type=BasicType('char'))

        elif p.slice[-1].type == "STR_CONSTANT":
            str_type = PointerType(type=BasicType('char'),
                                   array_size=[len(p[1])],
                                   array_type=BasicType('char'))
            p[0] = Node(name="constant", value=p[1], type=str_type)
        elif p.slice[-1].type == "NULL":
            p[0] = Node(name="constant",
                        value=p[1],
                        type=PointerType(type=Type()))
        else:
            p[0] = Node(name="constant", value=p[1], type=BasicType('bool'))
        p[0].constant = p[0].value

    else:
        p[0] = p[2]
예제 #10
0
def get_opcode(op=None, place1=None, place2=None, type=None):
    if isinstance(type, str):
        type = BasicType(type)
    assert "sconst@" not in place1 and "sconst@" not in place2, "string"
    if "const@" in place1 and "const@" in place2:
        return get_const(op_on_const(op, place1, place2), type=type), None
    tmp = get_newtmp(type)
    place1 = str(place1)
    place2 = str(place2)
    if op != "=":
        code = gen(op=op, place1=place1, place2=place2, place3=tmp)
        if "const@" in place1:
            const_use(place1)
        if "const@" in place2:
            const_use(place2)
    else:
        code = gen(op=op, place1=place1, place3=tmp)
        if "const@" in place1:
            const_use(place1)
    return tmp, code
예제 #11
0
def type_check_unary(node1, op, token, is_typename=False):
    allowed_base = {'int', 'float', 'double', 'char', 'long'}
    allowed_base_1 = {'int', 'char', 'long'}
    error = False
    if node1.type == "error":
        return Node(type="error")
    if op == "++" or op == "--":
        if node1.type.class_type == "BasicType" and node1.type.type in allowed_base:
            return Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
        if node1.type.class_type == "PointerType":
            return Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
        error = True
    elif op == "+" or op == "-":
        if node1.type.class_type == "BasicType" and node1.type.type in allowed_base:
            return Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
        error = True
    elif op == "&":
        return Node(name="unary_op",
                    value=op,
                    children=[node1],
                    type=PointerType(node1.type))
    elif op == "*":
        if node1.type.class_type == "PointerType":
            return Node(name="unary_op",
                        value=op,
                        children=[node1],
                        type=node1.type.type)
        Errors(errorType='TypeError',
               errorText="cannot dereference non-pointer type " +
               node1.type.stype,
               token_object=token)
        return Node(type="error")
    elif op == "~":
        if node1.type.class_type == "BasicType" and node1.type.type in allowed_base_1:
            return Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
        error = True
    elif op == "!":
        if node1.type.is_convertible_to(BasicType('bool')):
            return Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=BasicType('bool'))
        error = True
    elif op == "sizeof":
        if is_typename:
            return Node(name="unary_op",
                        value=op + ':' + node1.type.stype,
                        type=BasicType(type='long'))
        if isinstance(node1.type, Type) == False:
            Errors(errorType='TypeError',
                   errorText="cannot do sizeof on non type",
                   token_object=token)
            return Node(type="error")
        if node1.type.class_type in {'BasicType', 'PointerType', 'StructType'}:
            return Node(name="unary_op",
                        value=op,
                        type=BasicType(type='long'),
                        children=[node1])
        error = True

    if error:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype,
               token_object=token)
        return Node(type="error")
예제 #12
0
def type_check_unary(node1, op, token, is_typename=False):
    allowed_base = {'int', 'float', 'char', 'long'}
    allowed_base_1 = {'int', 'char', 'long'}
    error = False
    error_const = False
    if node1.type == "error":
        return Node(type="error")
    const = False
    if 'const@' in node1.place:
        const = True
    if (op == "++" or op == "--"):
        if const:
            error_const = True
        elif (node1.type.class_type == "BasicType" and node1.type.type
              in allowed_base) or node1.type.class_type == "PointerType":
            node = Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
            node.place = node1.place
            const_place = get_const(const=1, type=BasicType("long"))
            node_1 = Node(type=BasicType("long"))
            node_1.place = const_place
            node_assign = type_check_assign_op(node1,
                                               node_1,
                                               op=op[0] + "=",
                                               token=token)
            if node_assign.type == "error":
                return Node(type="error")
            node.code = node_assign.code
            return node
        # elif node1.type.class_type == "BasicType" and node1.type.type in allowed_base:
        #     node =  Node(name="unary_op",value=node1.type.stype+op,children=[node1],type=node1.type)
        #     node.code = node1.code
        #     const_place = get_const(const=1,type=node1.type,use=True)
        #     node.code += [gen(op=node1.type.stype+op[0],place1=node1.place,place2=const_place,place3=node1.place)]
        #     node.place = node1.place
        #     return node
        # elif node1.type.class_type == "PointerType":
        #     node = Node(name="unary_op",value=node1.type.stype+op,children=[node1],type=node1.type)
        #     node.code = node1.code
        #     width = node1.type.type_size
        #     const_place = get_const(const=width,type="long",use=True)
        #     node.code += [gen(op="long"+op[0],place1=node1.place,place2=const_place,place3=node1.place)]
        #     node.place = node1.place
        #     return node
        else:
            error = True
    elif op == "+" or op == "-":
        node1 = load_place(node1)
        if node1.type.class_type == "BasicType" and node1.type.type in allowed_base:
            node = Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
            if op == "+":
                node.place = node1.place
                return node
            if "const@" in node1.place:
                neg = -1 if op == "-" else 1
                node.place = get_const(neg * get_const_value(node1.place),
                                       type=node1.type)
                return node
            node.code = node1.code
            node.place = get_newtmp(type=node1.type)
            node.code += [
                gen(op="u" + node1.type.stype + op,
                    place1=node1.place,
                    place3=node.place)
            ]
            return node
        error = True
    elif op == "&":
        if const:
            error_const = True
        else:
            node = Node(name="unary_op",
                        value=op,
                        children=[node1],
                        type=PointerType(node1.type))
            node.code = node1.code
            if "load$" in node1.place:
                node.place = node1.place.split("load$")[-1]
                return node
            node.place = get_newtmp()
            node.code += [
                gen(op="addr",
                    place1=node1.place,
                    place3=node.place,
                    code=node.place + " = " + "addr(" + node1.place + ")")
            ]
            return node
    elif op == "*":
        node1 = load_place(node1)
        if const:
            error_const = True
        elif node1.type.class_type == "PointerType":
            node = Node(name="unary_op",
                        value=op,
                        children=[node1],
                        type=node1.type.type)
            if node.type.class_type == "PointerType":
                node.type.array_size = node1.type.array_size[1:]
            node.code = node1.code
            # node.place = get_newtmp(node1.type.type)
            # node.code += [gen(op="load",place1=node1.place,place3=node.place,code=node.place+" = "+"load("+node1.place+")")]
            node.place = "load$" + node1.place
            return node
        else:
            Errors(errorType='TypeError',
                   errorText="cannot dereference non-pointer type " +
                   node1.type.stype,
                   token_object=token)
            return Node(type="error")
    elif op == "~":
        node1 = load_place(node1)
        if node1.type.class_type == "BasicType" and node1.type.type in allowed_base_1:
            node = Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=node1.type)
            if "const@" in node1.place:
                node.place = get_const(~get_const_value(node1.place),
                                       type=node1.type)
                return node
            node.code = node1.code
            node.place = get_newtmp(type=node1.type)
            node.code += [
                gen(op=node1.type.stype + op,
                    place1=node1.place,
                    place3=node.place)
            ]
            return node
        error = True
    elif op == "!":
        node1 = load_place(node1)
        if node1.type.is_convertible_to(BasicType('bool')):
            node = Node(name="unary_op",
                        value=node1.type.stype + op,
                        children=[node1],
                        type=BasicType('bool'))
            if "const@" in node1.place:
                value = 0 if get_const_value(node1.place) == 0 else 1
                node.place = get_const(value, type='bool')
                return node
            node.code = node1.code
            node.place = get_newtmp(type=BasicType('bool'))
            node.code += [
                gen(op="not_bool", place1=node1.place, place3=node.place)
            ]
            return node
        error = True
    elif op == "sizeof":
        if is_typename:
            node = Node(name="unary_op",
                        value=op + ':' + node1.type.stype,
                        type=BasicType(type='long'))
            node.place = get_const(const=node1.type.width, type="long")
            # node.code += [gen(op="=",place1=str(node1.type.width),place3=node.place)]
            return node
        if isinstance(node1.type, Type) == False:
            Errors(errorType='TypeError',
                   errorText="cannot do sizeof on non type",
                   token_object=token)
            return Node(type="error")
        if node1.type.class_type in {'BasicType', 'PointerType', 'StructType'}:
            node = Node(name="unary_op",
                        value=op,
                        type=BasicType(type='long'),
                        children=[node1])
            node.place = get_const(const=node1.type.width, type="long")
            # node.code += [gen(op="=",place1=str(node1.type.width),place3=node.place)]
            return node
        error = True

    if error_const:
        Errors(errorType='TypeError',
               errorText=op + " not valid on constant",
               token_object=token)
        return Node(type="error")
    if error:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype,
               token_object=token)
        return Node(type="error")
예제 #13
0
def type_check_logical(node1, node2, op, token):
    allowed_class = {'BasicType', 'PointerType'}
    allowed_base = {'int', 'long', 'char', 'float', 'bool'}
    if node1.type == "error" or node2.type == "error":
        return Node(type="error")
    if "sconst@" in node1.place or "sconst@" in node2.place:
        Errors(errorType='TypeError',
               errorText=op + ' not support string constant',
               token_object=token)
        return Node(type="error")
    if node1.type.class_type not in allowed_class or node2.type.class_type not in allowed_class:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")
    if node1.type.class_type == "BasicType" and node1.type.type not in allowed_base:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")
    if node2.type.class_type == "BasicType" and node2.type.type not in allowed_base:
        Errors(errorType='TypeError',
               errorText=op + ' not support type ' + node1.type.stype + ',' +
               node2.type.stype,
               token_object=token)
        return Node(type="error")

    # if node1.type.type != "bool":
    #     node1 = typecast(node1,BasicType("bool"))
    # if node2.type.type != "bool":
    #     node2 = typecast(node2,BasicType("bool"))
    node = Node(name="binary_op",
                value=op,
                children=[node1, node2],
                type=BasicType('bool'))
    # node.code = node1.code + node2.code
    # tmp,code = get_opcode(op=op,place1=node1.place,place2=node2.place,type=BasicType('bool'))
    # node.code += [code]
    # node.place = tmp
    if op == "&&":
        if "const@" in node1.place and "const@" in node2.place:
            value = 1 if get_const_value(node1.place) and get_const_value(
                node2.place) else 0
            node.place = get_const(value, "bool")
            return node
        if "const@" in node1.place:
            const_use(node1.place)
        if "const@" in node2.place:
            const_use(node2.place)
        node.place = get_newtmp(BasicType('bool'))
        label1 = get_newlabel()
        label2 = get_newlabel()
        node.code = node1.code
        node.code += [gen(op="ifz", place1=node1.place, place2=label1)]
        node.code += node2.code
        node.code += [gen(op="ifz", place1=node2.place, place2=label1)]
        node.code += [
            gen(op="bool=",
                place1=get_const(1, type='bool', use=True),
                place3=node.place)
        ]
        node.code += [gen(op="goto", place1=label2)]
        node.code += [gen(op="label", place1=label1)]
        node.code += [
            gen(op="bool=",
                place1=get_const(0, type='bool', use=True),
                place3=node.place)
        ]
        node.code += [gen(op="label", place1=label2)]
    else:
        if "const@" in node1.place and "const@" in node2.place:
            value = 1 if get_const_value(node1.place) or get_const_value(
                node2.place) else 0
            node.place = get_const(value, "bool")
            return node
        if "const@" in node1.place:
            const_use(node1.place)
        if "const@" in node2.place:
            const_use(node2.place)
        node.place = get_newtmp(BasicType('bool'))
        label1 = get_newlabel()
        label2 = get_newlabel()
        node.code = node1.code
        node.code += [gen(op="ifnz", place1=node1.place, place2=label1)]
        node.code += node2.code
        node.code += [gen(op="ifnz", place1=node2.place, place2=label1)]
        node.code += [
            gen(op="bool=",
                place1=get_const(0, type='bool', use=True),
                place3=node.place)
        ]
        node.code += [gen(op="goto", place1=label2)]
        node.code += [gen(op="label", place1=label1)]
        node.code += [
            gen(op="bool=",
                place1=get_const(1, type='bool', use=True),
                place3=node.place)
        ]
        node.code += [gen(op="label", place1=label2)]
    return node