Exemple #1
0
def irarray(dtype, builder):
    base = dtype.base
    dims = dtype.dims
    pdepth = dtype.pdepth
    if len(dims) > 1:
        # Get the outer array
        arrlen, *rest = dims
        arrtyp = irtype(base, pdepth + len(rest), [arrlen])
        arraddr = builder.alloca(arrtyp)
        arraddr = builder.bitcast(arraddr, irtype(base, pdepth + len(dims),
                                                  []))
        # Build the inner arrays
        for i in range(arrlen):
            arrtype = DanaType(base, pdepth=pdepth, dims=dims[1:])
            addr = irarray(arrtype, builder)
            staddr = builder.gep(arraddr, [ir.Constant(ir.IntType(32), i)])
            builder.store(addr, staddr)
        return arraddr
    # Simple array
    elif dims:
        # Just allocate a variable
        base = irtype(base)
        size = dims[0]
        arrtyp = ir.ArrayType(base, size)
        arraddr = builder.alloca(arrtyp)
        addr = builder.bitcast(arraddr, ir.PointerType(base))
        return addr
    else:
        arrtyp = irtype(base)
        return builder.alloca(arrtyp)
Exemple #2
0
def produce_program(main_function):
    global_table = Table()
    global_table.function = Symbol(None, DanaType("void"))
    global_table.extend_funcs(builtins)

    return produce_function(main_function,
                            global_table=global_table,
                            is_main=True)
Exemple #3
0
def irgen_outro(func, function, table):
    outro = func.append_basic_block(name="outro")
    outro_builder = ir.IRBuilder(outro)

    # If the function is actually main, we have to enter an outro syscall to
    # be able to terminate properly - we do not have support routines like
    # crto0, so we make our own
    if function.is_main:
        outro_builder.call(table.funcs["exit"].func,
                           [ir.Constant(ir.IntType(8), 0)])

    if DanaType(function.symbol.type.base) == DanaType("void"):
        # Never reached for main, but used in void functions
        outro_builder.ret_void()
    else:
        outro_builder.unreachable()

    return outro
Exemple #4
0
    def __init__(self, d_lvalue, table):
        super().__init__()

        # The string case is self-contained
        string = d_lvalue.find_first_child("p_string")
        if string:
            value = ast.literal_eval(string.value) + "\0"
            dtype = DanaType("byte", dims=[len(value)])
            self._set_attributes([], dtype, "string", value)
            return

        # The function symbol
        name = d_lvalue.find_first("p_name").value
        table.check_scope(d_lvalue.linespan, name)

        # Get all indices
        d_exprs = d_lvalue.find_all("p_expr")
        exprs = [DanaExpr.factory(d_expr, table) for d_expr in d_exprs]
        for expr in exprs:
            expr.type.check_type(d_lvalue.linespan, DanaType("int"))

        # Make sure there are not too many indices
        base = table[name]
        total_dims = len(base.dims) + base.pdepth
        if total_dims < len(exprs):
            raise DanaType.DanaTypeError("Invalid dereferencing")

        # When we have both dimensions and pdepth, we have
        # a pointer to an array, not an array of pointers.
        # That influences the type of the dereferenced expression
        dims, pdepth = (base.dims, base.pdepth)
        if len(exprs) > base.pdepth:
            dims = base.dims[(len(exprs) - base.pdepth):]
            pdepth = 0
        else:
            dims = base.dims
            pdepth = base.pdepth - len(exprs)

        dtype = DanaType(base.base, \
                         dims=dims, \
                         pdepth=pdepth, \
                         args=base.args)

        self._set_attributes(exprs, dtype, "lvalue", value=name)
Exemple #5
0
    def __init__(self, operator, operand, table):
        optype = dict({
            "!": [DanaType("byte")],
            "+": [DanaType("int")],
            "-": [DanaType("int")],
            "not": [DanaType("logic"), DanaType("byte")],
        })
        renamed = dict({
            "!": "!",
            "+": "id",
            "(": "id",
            "-": "neg",
            "not": "not",
        })

        super().__init__()
        child = DanaExpr.factory(operand, table)
        if operator in optype:
            child.type.in_types(operand.linespan, optype[operator])

        self._set_attributes([child], child.type, renamed[operator])
Exemple #6
0
    def verify_call(self, d_stmt, table):
        """Verifies a proc call statement against a symbol table"""
        d_exprs = d_stmt.find_all("p_expr")

        proc_name = d_stmt.find_first("p_name").value
        self.value = proc_name

        exprs = [DanaExpr.factory(d_expr, table) for d_expr in d_exprs]
        self.exprs = exprs

        actual = DanaType("void", args=[expr.type for expr in exprs])
        table.check_table(d_stmt.linespan, Symbol(proc_name, actual))
Exemple #7
0
    def __init__(self, operator, arg1, arg2, table):
        renamed = dict({
            "STAR": "*",
            "SLASH": "/",
            "PERCENT": "%",
            "=": "==",
        })

        super().__init__()
        op1 = DanaExpr.factory(arg1, table)
        op2 = DanaExpr.factory(arg2, table)
        optype = op2.type
        optype.check_type(arg1.linespan, op1.type)

        if operator in self.binary_ops + self.comparison_ops:
            optype.in_types(arg1.linespan, [DanaType("int"), DanaType("byte")])

        if operator in self.bit_ops:
            optype.check_type(arg1.linespan, DanaType("byte"))

        if operator in self.logic_ops:
            logic_types = [
                DanaType("byte"),
                DanaType("logic"),
                DanaType("int")
            ]
            optype.check_type(arg1.linespan, logic_types)

        operator = renamed[operator] if operator in renamed else operator
        self._set_attributes([op1, op2], op1.type, operator)
Exemple #8
0
def get_function_symbol(d_function, is_main=False):
    """Get the name, type, and argument types of a function"""
    d_header = d_function.find_first("p_header")

    # If this is the program and not just a function, set the name accordingly
    name = d_header.find_first("p_name").value
    if is_main:
        name = "main"

    d_type = d_header.find_first("p_maybe_data_type").find_first("p_data_type")
    base = d_type.value if d_type else "void"

    args = []
    fpars = d_header.find_all("p_fpar_def")
    for fpar in fpars:
        ftype = get_type(fpar.find_first("p_fpar_type"))
        args += [ftype] * len(fpar.find_all("p_name"))

    return Symbol(name, DanaType(base, args=args))
Exemple #9
0
 def __init__(self):
     self._set_attributes([], DanaType("invalid"), None)
Exemple #10
0
def get_type(d_type):
    base = d_type.find_first("p_data_type").value
    dims = list(const.value for const in d_type.find_all("p_number"))
    pdepth = 1 if d_type.find_first("p_empty_brackets") else 0
    is_ref = True if d_type.find_first("p_ref") else False
    return DanaType(base, dims=dims, pdepth=pdepth, is_ref=is_ref)
Exemple #11
0
import sys
from copy import copy
from compiler.semantic.type import DanaType
from compiler.semantic.table import Table, Symbol
from compiler.semantic.func import DanaFunction
from compiler.semantic.block import DanaContainer

builtins = [
    Symbol("writeInteger", DanaType("void", args=[DanaType("int")])),
    Symbol("writeByte", DanaType("void", args=[DanaType("byte")])),
    Symbol("writeChar", DanaType("void", args=[DanaType("byte")])),
    Symbol("writeString", DanaType("void", args=[DanaType("byte", pdepth=1)])),
    Symbol("readInteger", DanaType("int", args=[])),
    Symbol("readByte", DanaType("byte", args=[])),
    Symbol("readChar", DanaType("byte", args=[])),
    Symbol(
        "readString",
        DanaType("void", args=[DanaType("int"),
                               DanaType("byte", pdepth=1)])),
    Symbol("strlen", DanaType("int", args=[DanaType("byte", pdepth=1)])),
    Symbol(
        "strcmp",
        DanaType("int",
                 args=[DanaType("byte", pdepth=1),
                       DanaType("byte", pdepth=1)])),
    Symbol(
        "strcat",
        DanaType("byte",
                 pdepth=1,
                 args=[DanaType("byte", pdepth=1),
                       DanaType("byte", pdepth=1)])),