#include "cangjie/CHIR/IR/IntrinsicKind.h"
#include "cangjie/CHIR/AST2CHIR/TranslateASTNode/Translator.h"
using namespace Cangjie::CHIR;
using namespace Cangjie;
Ptr<Value> Translator::Visit(const AST::SubscriptExpr& subscriptExpr)
{
CJC_ASSERT(subscriptExpr.indexExprs.size() == 1);
if (subscriptExpr.isTupleAccess) {
return TranslateTupleAccess(subscriptExpr);
}
if (subscriptExpr.IsVArrayAccess()) {
return TranslateVArrayAccess(subscriptExpr);
}
CJC_ASSERT(false && "Certainly won't get here in translating subscriptExpr.");
return nullptr;
}
Ptr<Value> Translator::TranslateTupleAccess(const AST::SubscriptExpr& subscriptExpr)
{
const auto& loc = TranslateLocation(subscriptExpr);
auto se = &subscriptExpr;
std::list<uint64_t> indexs;
AST::Expr* baseExpr = nullptr;
for (; se != nullptr && se->isTupleAccess; se = DynamicCast<AST::SubscriptExpr*>(se->baseExpr.get())) {
baseExpr = se->baseExpr.get();
indexs.emplace_front(se->indexExprs[0]->constNumValue.asInt.Uint64());
}
CJC_NULLPTR_CHECK(baseExpr);
auto base = TranslateExprArg(*baseExpr);
if (base->GetType()->IsRef()) {
base = CreateAndAppendExpression<Load>(
loc, StaticCast<RefType*>(base->GetType())->GetBaseType(), base, currentBlock)->GetResult();
}
auto res = CreateAndAppendExpression<Field>(loc, chirTy.TranslateType(*subscriptExpr.GetTy()), base,
std::vector<uint64_t>(indexs.cbegin(), indexs.cend()), currentBlock);
If the SubscriptExpr is added by compiler, DCE will skip it.
for example code:
let a:Int64
let b:Int64
(a, b, _) = (1, 2, 3) --------> var tmp = (1, 2, 3); a = tmp[0]; b =tmp[1]; _= tmp[2]
*/
if (subscriptExpr.TestAttr(AST::Attribute::IMPLICIT_ADD)) {
res->Set<SkipCheck>(SkipKind::SKIP_DCE_WARNING);
}
return res->GetResult();
}
Ptr<Value> Translator::TranslateVArrayAccess(const AST::SubscriptExpr& subscriptExpr)
{
const auto& loc = TranslateLocation(subscriptExpr);
auto se = &subscriptExpr;
std::vector<Value*> indexs;
std::vector<AST::Expr*> indexExprs;
AST::Expr* baseExpr = nullptr;
for (; se != nullptr && se->IsVArrayAccess(); se = DynamicCast<AST::SubscriptExpr*>(se->baseExpr.get())) {
baseExpr = se->baseExpr.get();
indexExprs.push_back(se->indexExprs[0].get());
}
CJC_NULLPTR_CHECK(baseExpr);
for (auto it = indexExprs.crbegin(); it != indexExprs.crend(); ++it) {
auto index = TranslateExprArg(**it);
if (index->GetType()->IsRef()) {
index = CreateAndAppendExpression<Load>(
StaticCast<RefType*>(index->GetType())->GetBaseType(), index, currentBlock)->GetResult();
}
indexs.push_back(index);
}
auto base = TranslateExprArg(*baseExpr);
indexs.insert(indexs.begin(), base);
auto callContext = IntrisicCallContext {
.kind = IntrinsicKind::VARRAY_GET,
.args = indexs
};
return CreateAndAppendExpression<Intrinsic>(
loc, chirTy.TranslateType(*subscriptExpr.GetTy()), callContext, currentBlock)
->GetResult();
}