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])
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