mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[FunC] Auto-inline functions-wrappers T f(...args) { return anotherF(...args); }
This will allow to easily implement camelCase wrappers aside stdlib, even without changing hashes of existing contracts. Also, stdlib renamings could be easily performed in the same manner, even with arguments reordered.
This commit is contained in:
parent
bac4e3df97
commit
18050a7591
12 changed files with 929 additions and 60 deletions
|
@ -340,16 +340,36 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
|
|||
}
|
||||
case _Apply: {
|
||||
func_assert(sym);
|
||||
auto func = dynamic_cast<SymValFunc*>(sym->value);
|
||||
std::vector<var_idx_t> res;
|
||||
if (func && func->arg_order.size() == args.size() && !(code.flags & CodeBlob::_ComputeAsmLtr)) {
|
||||
SymDef* applied_sym = sym;
|
||||
auto func = dynamic_cast<SymValFunc*>(applied_sym->value);
|
||||
// replace `beginCell()` with `begin_cell()`
|
||||
if (func && func->is_just_wrapper_for_another_f()) {
|
||||
// body is { Op::_Import; Op::_Call; Op::_Return; }
|
||||
const Op *op_call = dynamic_cast<SymValCodeFunc*>(func)->code->ops.get();
|
||||
while (op_call->cl != Op::_Call) {
|
||||
op_call = op_call->next.get();
|
||||
}
|
||||
applied_sym = op_call->fun_ref;
|
||||
func = dynamic_cast<SymValFunc*>(applied_sym->value);
|
||||
// soon we'll get rid of this pragma: it will be always on, we'll pass just {} here and below
|
||||
bool compute_asm_ltr = code.flags & CodeBlob::_ComputeAsmLtr;
|
||||
// a function may call anotherF with shuffled arguments: f(x,y) { return anotherF(y,x) }
|
||||
// then op_call looks like (_1,_0), so use op_call->right for correct positions in Op::_Call below
|
||||
// it's correct, since every argument has width 1
|
||||
std::vector<var_idx_t> res_inner = pre_compile_tensor(args, code, lval_globs, compute_asm_ltr ? std::vector<var_idx_t>{} : func->arg_order);
|
||||
res.reserve(res_inner.size());
|
||||
for (var_idx_t right_idx : op_call->right) {
|
||||
res.emplace_back(res_inner[right_idx]);
|
||||
}
|
||||
} else if (func && func->arg_order.size() == args.size() && !(code.flags & CodeBlob::_ComputeAsmLtr)) {
|
||||
//std::cerr << "!!! reordering " << args.size() << " arguments of " << sym->name() << std::endl;
|
||||
res = pre_compile_tensor(args, code, lval_globs, func->arg_order);
|
||||
} else {
|
||||
res = pre_compile_tensor(args, code, lval_globs, {});
|
||||
}
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), sym);
|
||||
auto& op = code.emplace_back(here, Op::_Call, rvect, res, applied_sym);
|
||||
if (flags & _IsImpure) {
|
||||
op.flags |= Op::_Impure;
|
||||
}
|
||||
|
@ -364,7 +384,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
|
|||
}
|
||||
return {val};
|
||||
case _VarApply:
|
||||
if (args[0]->cls == _Glob) {
|
||||
if (args[0]->cls == _GlobFunc) {
|
||||
auto res = args[1]->pre_compile(code);
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), args[0]->sym);
|
||||
|
@ -388,8 +408,14 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code, std::vector<std::pair<S
|
|||
code.emplace_back(here, Op::_IntConst, rvect, intval);
|
||||
return rvect;
|
||||
}
|
||||
case _Glob:
|
||||
case _GlobFunc:
|
||||
case _GlobVar: {
|
||||
if (auto fun_ref = dynamic_cast<SymValFunc*>(sym->value)) {
|
||||
fun_ref->flags |= SymValFunc::flagUsedAsNonCall;
|
||||
if (!fun_ref->arg_order.empty() || !fun_ref->ret_order.empty()) {
|
||||
throw src::ParseError(here, "Saving " + sym->name() + " into a variable will most likely lead to invalid usage, since it changes the order of variables on the stack");
|
||||
}
|
||||
}
|
||||
auto rvect = new_tmp_vect(code);
|
||||
if (lval_globs) {
|
||||
lval_globs->push_back({ sym, rvect[0] });
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue