def visit_print(self, node):
     if node.value:
         val = self.visit(node.value)
     else:
         self.call('putchar', [ir.Constant(type_map[INT32], 10)])
         return
     if isinstance(val.type, ir.IntType):
         if val.type.width == 1:
             array = self.create_array(type_map[INT])
             self.call('@bool_to_str', [array, val])
             val = array
         else:
             if int(str(val.type).split("i")[1]) == 8:
                 self.print_num("%c", val)
             elif val.type.signed:
                 if int(str(val.type).split("i")[1]) < 32:
                     val = self.builder.sext(val, type_map[INT32])
                     self.print_num("%d", val)
                 elif int(str(val.type).split("i")[1]) == 32:
                     self.print_num("%d", val)
                 else:
                     self.print_num("%lld", val)
             else:
                 if int(str(val.type).split("i")[1]) <= 32:
                     self.print_num("%u", val)
                 else:
                     self.print_num("%llu", val)
             return
     elif isinstance(val.type, (ir.FloatType, ir.DoubleType)):
         if isinstance(val.type, ir.FloatType):
             val = cast_ops(self, val, ir.DoubleType(), node)
         self.print_num("%g", val)
         return
     self.call('print', [val])
Example #2
0
    def visit_assign(self, node):
        if isinstance(node.right, DotAccess) and self.search_scopes(node.right.obj).type == ENUM or \
           hasattr(node.right, 'name') and isinstance(self.search_scopes(node.right.name), ir.IdentifiedStructType):
            var_name = node.left.value if isinstance(node.left.value, str) else node.left.value.value
            self.define(var_name, self.visit(node.right))
        elif hasattr(node.right, 'value') and isinstance(self.search_scopes(node.right.value), ir.Function):
            self.define(node.left.value, self.search_scopes(node.right.value))
        else:
            if isinstance(node.right, Input):
                if hasattr(node.left, 'type'):
                    node.right.type = node.left.type
                else:
                    node.right.type = str
            var = self.visit(node.right)
            if not var:
                return
            if isinstance(node.left, VarDecl):
                var_name = node.left.value.value
                if node.left.type.value in (LIST, TUPLE):
                    # TODO: Currently only supporting one type for lists and tuples
                    var_type = type_map[list(node.left.type.func_params.items())[0][1].value]
                    self.alloc_define_store(var, var_name, var.type)
                else:
                    var_type = type_map[node.left.type.value]
                    if not var.type.is_pointer:
                        casted_value = cast_ops(self, var, var_type, node)
                        self.alloc_define_store(casted_value, var_name, var_type)
                    else:  # TODO: Not able currently to deal with pointers, such as functions
                        self.alloc_define_store(var, var_name, var.type)
            elif isinstance(node.left, DotAccess):
                obj = self.search_scopes(node.left.obj)
                obj_type = self.search_scopes(obj.type.pointee.name.split('.')[-1])
                idx = -1
                for i, v in enumerate(obj_type.fields):
                    if v == node.left.field:
                        idx = i
                        break

                elem = self.builder.gep(obj, [self.const(0, width=INT32), self.const(idx, width=INT32)], inbounds=True)
                self.builder.store(self.visit(node.right), elem)
            elif isinstance(node.left, CollectionAccess):
                right = self.visit(node.right)
                array_type = str(self.search_scopes(node.left.collection.value).type.pointee.elements[-1].pointee)
                self.call('{}_array_set'.format(array_type), [self.search_scopes(node.left.collection.value), self.const(node.left.key.value), right])
            else:
                var_name = node.left.value
                var_value = self.top_scope.get(var_name)
                if var_value:
                    if isinstance(var_value, float):
                        node.right.value = float(node.right.value)
                    self.store(var, var_name)
                elif isinstance(var, ir.Function):
                    self.define(var_name, var)
                else:
                    self.alloc_define_store(var, var_name, var.type)
    def visit_opassign(self, node):
        right = self.visit(node.right)
        collection_access = None
        key = None
        if isinstance(node.left, CollectionAccess):
            collection_access = True
            var_name = self.search_scopes(node.left.collection.value)
            array_type = str(self.search_scopes(node.left.collection.value).type.pointee.elements[-1].pointee)
            key = self.const(node.left.key.value)
            var = self.call('{}.array.ver'.format(array_type), [var_name, key])
            pointee = var.type
        else:
            var_name = node.left.value
            var = self.load(var_name)
            pointee = self.search_scopes(var_name).type.pointee
        op = node.op
        right = cast_ops(self, right, var.type, node)
        if isinstance(pointee, ir.IntType):
            if op == PLUS_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.add(var, right)
            elif op == MINUS_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.sub(var, right)
            elif op == MUL_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.mul(var, right)
            elif op == FLOORDIV_ASSIGN:
                temp = cast_ops(self, var, ir.DoubleType(), node)
                temp_right = cast_ops(self, right, ir.DoubleType(), node)
                temp = self.builder.fdiv(temp, temp_right)
                res = cast_ops(self, temp, var.type, node)
            elif op == DIV_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.sdiv(var, right)
            elif op == MOD_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.srem(var, right)
            elif op == POWER_ASSIGN:
                if not isinstance(node.right.value, int):
                    error('Cannot use non-integers for power coeficient')
                    # TODO: Send me to typechecker and check for binop as well

                right = cast_ops(self, right, var.type, node)
                temp = self.alloc_and_store(var, type_map[INT])
                for _ in range(node.right.value - 1):
                    res = self.builder.mul(self.load(temp), var)
                    self.store(res, temp)
                res = self.load(temp)
            else:
                raise NotImplementedError()
        elif isinstance(pointee, ir.DoubleType) or isinstance(pointee, ir.FloatType):
            if op == PLUS_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.fadd(var, right)
            elif op == MINUS_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.fsub(var, right)
            elif op == MUL_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.fmul(var, right)
            elif op == FLOORDIV_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.fdiv(var, right)
                temp = cast_ops(self, res, ir.IntType(64), node)
                res = cast_ops(self, temp, res.type, node)
            elif op == DIV_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.fdiv(var, right)
            elif op == MOD_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                res = self.builder.frem(var, right)
            elif op == POWER_ASSIGN:
                right = cast_ops(self, right, var.type, node)
                temp = self.alloc_and_store(var, type_map[DOUBLE])
                for _ in range(node.right.value - 1):
                    res = self.builder.fmul(self.load(temp), var)
                    self.store(res, temp)
                res = self.load(temp)
            else:
                raise NotImplementedError()
        else:
            raise NotImplementedError()

        if collection_access:
            self.call('{}.array.preparar'.format(array_type), [var_name, key, res])
        else:
            self.store(res, var_name)
    def comp_cast(self, arg, typ, node):
        if types_compatible(str(arg.type), typ):
            return cast_ops(self, arg, typ, node)

        return arg