llvm::Type *emit_alloc_type(T const& t) { auto const ty = emit(t); if (ty->isPointerTy()) { return ty->getPointerElementType(); } else { return ty; } }
TCResult ast::SliceOp::typecheck(sst::TypecheckState* fs, fir::Type* inferred) { fs->pushLoc(this); defer(fs->popLoc()); fs->pushAnonymousTree(); defer(fs->popTree()); auto array = this->expr->typecheck(fs).expr(); auto ty = array->type; fs->enterSubscript(array); defer(fs->leaveSubscript()); fir::Type* elm = 0; if(ty->isDynamicArrayType() || ty->isArraySliceType() || ty->isArrayType()) elm = ty->getArrayElementType(); else if(ty->isStringType()) elm = fir::Type::getInt8(); else if(ty->isPointerType()) elm = ty->getPointerElementType(); else error(array, "invalid type '%s' for slice operation", ty); auto begin = this->start ? this->start->typecheck(fs, fir::Type::getInt64()).expr() : 0; auto end = this->end ? this->end->typecheck(fs, fir::Type::getInt64()).expr() : 0; if(begin && !begin->type->isIntegerType()) error(begin, "expected integer type for start index of slice; found '%s'", begin->type); if(end && !end->type->isIntegerType()) error(end, "expected integer type for end index of slice; found '%s'", end->type); //* how it goes: // 1. strings and dynamic arrays are always sliced mutably. // 2. slices of slices naturally inherit their mutability. // 3. arrays are sliced immutably. // 4. pointers inherit their mutability as well. bool ismut = sst::getMutabilityOfSliceOfType(ty); auto ret = util::pool<sst::SliceOp>(this->loc, fir::ArraySliceType::get(elm, ismut)); ret->expr = array; ret->begin = begin; ret->end = end; return TCResult(ret); }