Skip to content

Commit 8ef7ac1

Browse files
committed
Add common infra for types and exprs instantiattion
1 parent 29139ab commit 8ef7ac1

8 files changed

Lines changed: 60 additions & 59 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5045,15 +5045,16 @@ std::string Converter::ConvertTake(clang::Expr *arg) {
50455045

50465046
std::string Converter::ConvertMappedMethodCall(
50475047
clang::Expr *expr, const TranslationRule::MethodCallFragment &mc,
5048-
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx) {
5049-
return ConvertIRFragment(mc.receiver, expr, args, num_args, ctx) +
5050-
ConvertIRFragment(mc.body, expr, args, num_args, ctx);
5048+
llvm::ArrayRef<clang::TemplateArgument> bindings, clang::Expr **args,
5049+
unsigned num_args, TempMaterializationCtx *ctx) {
5050+
return ConvertIRFragment(mc.receiver, bindings, expr, args, num_args, ctx) +
5051+
ConvertIRFragment(mc.body, bindings, expr, args, num_args, ctx);
50515052
}
50525053

50535054
std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args,
50545055
unsigned num_args,
50555056
TempMaterializationCtx *ctx) {
5056-
auto *tgt_ir = RuleRegistry::GetExprRule(ctx_, expr);
5057+
auto [tgt_ir, bindings] = RuleRegistry::Search(ctx_, expr);
50575058
if (!tgt_ir)
50585059
return {};
50595060

@@ -5062,8 +5063,8 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args,
50625063
auto saved_borrows = std::exchange(mut_borrows_, {});
50635064
auto *operand = tgt_ir->refExprOperand();
50645065
bool lvalue = operand && !isAddrOf();
5065-
auto result = ConvertIRFragment(lvalue ? *operand : tgt_ir->body, expr, args,
5066-
num_args, ctx);
5066+
auto result = ConvertIRFragment(lvalue ? *operand : tgt_ir->body, bindings,
5067+
expr, args, num_args, ctx);
50675068
if (tgt_ir->multi_statement) {
50685069
result = '{' + result + '}';
50695070
}
@@ -5077,21 +5078,28 @@ std::string Converter::GetMappedAsString(clang::Expr *expr, clang::Expr **args,
50775078

50785079
std::string Converter::ConvertIRFragment(
50795080
const std::vector<TranslationRule::BodyFragment> &fragments,
5080-
clang::Expr *expr, clang::Expr **args, unsigned num_args,
5081-
TempMaterializationCtx *ctx) {
5081+
llvm::ArrayRef<clang::TemplateArgument> bindings, clang::Expr *expr,
5082+
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx) {
50825083
using namespace TranslationRule;
50835084

5084-
auto all_args = BuildUnifiedArgs(expr, args, num_args);
5085+
std::vector<clang::Expr *> all_args;
5086+
if (expr) {
5087+
all_args = BuildUnifiedArgs(expr, args, num_args);
5088+
}
50855089

50865090
std::string result;
50875091
for (auto &frag : fragments) {
50885092
if (auto *t = std::get_if<TextFragment>(&frag)) {
50895093
result += t->text;
50905094
} else if (auto *g = std::get_if<GenericFragment>(&frag)) {
5091-
result += Mapper::InstantiateTemplate(*this, expr, g->n);
5095+
result += GetTemplateArgumentAsString(bindings[g->n - 1]);
50925096
} else if (auto *d = std::get_if<DefaultFragment>(&frag)) {
5093-
result += Mapper::InstantiateTemplateDefault(*this, expr, d->n);
5097+
auto &arg = bindings[d->n - 1];
5098+
assert(arg.getKind() == clang::TemplateArgument::Type &&
5099+
"default of a non-type generic");
5100+
result += GetUnboxedDefaultAsString(arg.getAsType());
50945101
} else if (auto *ph = std::get_if<PlaceholderFragment>(&frag)) {
5102+
assert(expr && "placeholder outside an expression rule");
50955103
auto arg_idx = ph->n;
50965104
assert(arg_idx < all_args.size());
50975105
auto *arg = all_args[arg_idx];
@@ -5116,16 +5124,20 @@ std::string Converter::ConvertIRFragment(
51165124
};
51175125
result += ConvertPlaceholder(expr, arg, ph_ctx);
51185126
} else if (std::get_if<TranslationRule::VaArgsFragment>(&frag)) {
5127+
assert(expr && "variadic arguments outside an expression rule");
51195128
result += ConvertVariadicTail(expr, all_args);
51205129
} else if (std::get_if<TranslationRule::InitFragment>(&frag)) {
5130+
assert(expr && "init outside an expression rule");
51215131
result += ConvertInitFragment(expr, all_args);
51225132
} else if (auto *mc =
51235133
std::get_if<std::unique_ptr<MethodCallFragment>>(&frag)) {
5124-
result += ConvertMappedMethodCall(expr, **mc, args, num_args, ctx);
5134+
result +=
5135+
ConvertMappedMethodCall(expr, **mc, bindings, args, num_args, ctx);
51255136
} else if (auto *re =
51265137
std::get_if<std::unique_ptr<RefExprFragment>>(&frag)) {
51275138
result += (*re)->prefix + ' ' +
5128-
ConvertIRFragment((*re)->inner, expr, args, num_args, ctx);
5139+
ConvertIRFragment((*re)->inner, bindings, expr, args, num_args,
5140+
ctx);
51295141
}
51305142
}
51315143

‎cpp2rust/converter/converter.h‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
9494

9595
virtual std::string GetUnboxedDefaultAsString(clang::QualType qual_type);
9696

97+
std::string
98+
ConvertIRFragment(const std::vector<TranslationRule::BodyFragment> &fragments,
99+
llvm::ArrayRef<clang::TemplateArgument> bindings,
100+
clang::Expr *expr, clang::Expr **args, unsigned num_args,
101+
TempMaterializationCtx *ctx);
102+
97103
std::string GetTemplateArgumentAsString(const clang::TemplateArgument &arg);
98104

99105
bool VisitRecoveryExpr(clang::RecoveryExpr *expr);
@@ -836,11 +842,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
836842
unsigned num_args = 0,
837843
TempMaterializationCtx *ctx = nullptr);
838844

839-
std::string
840-
ConvertIRFragment(const std::vector<TranslationRule::BodyFragment> &fragments,
841-
clang::Expr *expr, clang::Expr **args, unsigned num_args,
842-
TempMaterializationCtx *ctx);
843-
844845
std::string ConvertPlaceholder(clang::Expr *expr, clang::Expr *arg,
845846
const PlaceholderCtx &ph_ctx);
846847

@@ -870,7 +871,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
870871

871872
virtual std::string ConvertMappedMethodCall(
872873
clang::Expr *expr, const TranslationRule::MethodCallFragment &mc,
873-
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx);
874+
llvm::ArrayRef<clang::TemplateArgument> bindings, clang::Expr **args,
875+
unsigned num_args, TempMaterializationCtx *ctx);
874876

875877
virtual std::string AccessLValueObject(clang::MemberExpr *member);
876878

‎cpp2rust/converter/mapper.cpp‎

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,25 +44,6 @@ std::string MapFunctionName(clang::ASTContext &ctx,
4444
return GetNamedDeclAsString(decl->getCanonicalDecl());
4545
}
4646

47-
std::string InstantiateTemplate(Converter &converter, const clang::Expr *expr,
48-
unsigned n) {
49-
auto [rule, subs] = RuleRegistry::Search(converter.GetASTContext(), expr);
50-
if (!rule) {
51-
return std::format("T{}", n);
52-
}
53-
return Matcher::MapBinding(converter, subs, n - 1);
54-
}
55-
56-
std::string InstantiateTemplateDefault(Converter &converter,
57-
const clang::Expr *expr, unsigned n) {
58-
auto [rule, subs] = RuleRegistry::Search(converter.GetASTContext(), expr);
59-
assert(rule && "default of a generic outside a matched rule");
60-
auto &arg = subs.at(n - 1);
61-
assert(arg.getKind() == clang::TemplateArgument::Type &&
62-
"default of a non-type generic");
63-
return converter.GetUnboxedDefaultAsString(arg.getAsType());
64-
}
65-
6647
std::string Map(clang::ASTContext &ctx, clang::QualType qual_type) {
6748
auto rule = RuleRegistry::Search(ctx, qual_type).first;
6849
return rule ? rule->type_info.type : std::string();
@@ -81,7 +62,8 @@ std::string MapInitializer(Converter &converter, clang::QualType qual_type) {
8162
auto [rule, subs] =
8263
RuleRegistry::Search(converter.GetASTContext(), qual_type);
8364
if (rule && !rule->initializer.empty()) {
84-
return Matcher::InstantiateTgt(converter, subs, rule->initializer);
65+
return converter.ConvertIRFragment(rule->initializer, subs, nullptr,
66+
nullptr, 0, nullptr);
8567
}
8668
return {};
8769
}

‎cpp2rust/converter/mapper.h‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,6 @@ std::string Map(Converter &converter, clang::QualType qual_type);
2525
std::string MapInitializer(Converter &converter, clang::QualType qual_type);
2626
std::string MapFunctionName(clang::ASTContext &ctx,
2727
const clang::FunctionDecl *decl);
28-
std::string InstantiateTemplate(Converter &converter, const clang::Expr *expr,
29-
unsigned n);
30-
31-
std::string InstantiateTemplateDefault(Converter &converter,
32-
const clang::Expr *expr, unsigned n);
3328
std::string GetParamType(Converter &converter, const clang::Expr *expr,
3429
unsigned index);
3530
std::string GetReturnType(Converter &converter, const clang::Expr *expr);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,11 +2977,13 @@ std::string ConverterRefCount::ConvertTake(clang::Expr *arg) {
29772977

29782978
std::string ConverterRefCount::ConvertMappedMethodCall(
29792979
clang::Expr *expr, const TranslationRule::MethodCallFragment &mc,
2980-
clang::Expr **args, unsigned num_args, TempMaterializationCtx *ctx) {
2980+
llvm::ArrayRef<clang::TemplateArgument> bindings, clang::Expr **args,
2981+
unsigned num_args, TempMaterializationCtx *ctx) {
29812982
auto receiver_ph = mc.getReceiverPlaceholder();
29822983
if (!receiver_ph || receiver_ph->access == TranslationRule::Access::kBorrow ||
29832984
receiver_ph->access == TranslationRule::Access::kMove) {
2984-
return Converter::ConvertMappedMethodCall(expr, mc, args, num_args, ctx);
2985+
return Converter::ConvertMappedMethodCall(expr, mc, bindings, args,
2986+
num_args, ctx);
29852987
}
29862988

29872989
auto arg_idx = receiver_ph->n;
@@ -2996,22 +2998,26 @@ std::string ConverterRefCount::ConvertMappedMethodCall(
29962998
if (arg->getType()->isPointerType()) {
29972999
return std::format("{}.with_mut(|__v: {}| __v{})", ConvertPointer(arg),
29983000
param_type,
2999-
ConvertIRFragment(mc.body, expr, args, num_args, ctx));
3001+
ConvertIRFragment(mc.body, bindings, expr, args,
3002+
num_args, ctx));
30003003
}
30013004

30023005
// A receiver reached through a pointer is modified through it, only for
30033006
// the call, after the other arguments are computed.
30043007
std::string receiver;
30053008
{
30063009
ScopedValue in_receiver(in_receiver_, true);
3007-
receiver = ConvertIRFragment(mc.receiver, expr, args, num_args, ctx);
3010+
receiver =
3011+
ConvertIRFragment(mc.receiver, bindings, expr, args, num_args, ctx);
30083012
}
30093013
if (pending_deref_.empty()) {
3010-
return receiver + ConvertIRFragment(mc.body, expr, args, num_args, ctx);
3014+
return receiver +
3015+
ConvertIRFragment(mc.body, bindings, expr, args, num_args, ctx);
30113016
}
30123017

30133018
auto ptr = pending_deref_.take();
3014-
auto body = ConvertIRFragment(mc.body, expr, args, num_args, ctx);
3019+
auto body =
3020+
ConvertIRFragment(mc.body, bindings, expr, args, num_args, ctx);
30153021
MarkFresh();
30163022

30173023
return std::format("{}.with_mut(|__v: {}| __v{})", ptr, param_type, body);

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ class ConverterRefCount final : public Converter {
324324
std::string
325325
ConvertMappedMethodCall(clang::Expr *expr,
326326
const TranslationRule::MethodCallFragment &mc,
327+
llvm::ArrayRef<clang::TemplateArgument> bindings,
327328
clang::Expr **args, unsigned num_args,
328329
TempMaterializationCtx *ctx) override;
329330

‎cpp2rust/converter/translation_rule.cpp‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,10 @@ void TypeRule::dump() const {
251251
type_info.dump();
252252
log() << '\n';
253253
if (!initializer.empty()) {
254-
log() << " init: " << initializer << '\n';
254+
log() << " init:\n";
255+
for (auto &frag : initializer) {
256+
BodyFragmentDump(frag);
257+
}
255258
}
256259
}
257260

@@ -304,8 +307,8 @@ ExprRule ParseExprRuleJSON(const llvm::json::Object &obj) {
304307

305308
TypeRule ParseTypeRuleJSON(const llvm::json::Object &obj) {
306309
TypeRule rule;
307-
if (auto init = obj.getString("init"))
308-
rule.initializer = init->str();
310+
if (auto *init = obj.getArray("init"))
311+
rule.initializer = ParseBodyFragmentsJSON(*init);
309312
if (auto generic = obj.getInteger("generic"))
310313
rule.generic = *generic;
311314
rule.type_info = ParseTypeInfoJSON(obj);

‎cpp2rust/converter/translation_rule.h‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ struct InitFragment {
5858
struct MethodCallFragment; // forward declaration
5959
struct RefExprFragment;
6060

61-
using BodyFragment = std::variant<TextFragment, PlaceholderFragment,
62-
GenericFragment, DefaultFragment,
63-
VaArgsFragment, InitFragment,
64-
std::unique_ptr<MethodCallFragment>,
65-
std::unique_ptr<RefExprFragment>>;
61+
using BodyFragment =
62+
std::variant<TextFragment, PlaceholderFragment, GenericFragment,
63+
DefaultFragment, VaArgsFragment, InitFragment,
64+
std::unique_ptr<MethodCallFragment>,
65+
std::unique_ptr<RefExprFragment>>;
6666

6767
struct MethodCallFragment {
6868
std::vector<BodyFragment> receiver;
@@ -108,7 +108,7 @@ struct ExprRule {
108108
};
109109

110110
struct TypeRule {
111-
std::string initializer; // Rust initializer expression
111+
std::vector<BodyFragment> initializer; // Rust initializer expression
112112
unsigned generic = 0;
113113
TypeInfo type_info;
114114

0 commit comments

Comments
 (0)