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)
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)
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
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)
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])
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))
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)
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))
def __init__(self): self._set_attributes([], DanaType("invalid"), None)
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)
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)])),