mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
func/fift: bugfixes
This commit is contained in:
parent
f67f5d879b
commit
38c3e39066
41 changed files with 248 additions and 99 deletions
|
@ -756,6 +756,12 @@ x{EDF9} @Defop BOOLEVAL
|
|||
{ PUSHINT c3 PREPAREVAR } cond
|
||||
} dup : PREPARE : PREPAREDICT
|
||||
//
|
||||
// inline support
|
||||
{ dup sbits { @addop } {
|
||||
dup srefs 1- abort"exactly one reference expected in inline"
|
||||
ref@ CALLREF } cond
|
||||
} : INLINE
|
||||
//
|
||||
// throwing and handling exceptions
|
||||
{ dup 6 ufits
|
||||
{ <b x{F22_} s, swap 6 u, }
|
||||
|
@ -1047,6 +1053,7 @@ x{FFF0} @Defop SETCPX
|
|||
//
|
||||
variable @proccnt
|
||||
variable @proclist
|
||||
variable @procdict
|
||||
19 constant @procdictkeylen
|
||||
{ @proclist @ cons @proclist ! } : @proclistadd
|
||||
{ dup @procdictkeylen fits not abort"procedure index out of range"
|
||||
|
@ -1061,26 +1068,39 @@ variable @proclist
|
|||
{ swap @declproc }
|
||||
cond } : DECLMETHOD
|
||||
"main" @proclistadd
|
||||
dictnew
|
||||
dictnew @procdict !
|
||||
} : PROGRAM{
|
||||
{ dup sbits 1000 > { s>c <b swap ref, b> <s } if } : @adj-long-proc
|
||||
{ // d i s
|
||||
@adj-long-proc swap rot @procdictkeylen idict!+ not abort"cannot define procedure, redefined?"
|
||||
} : PROC
|
||||
{ 2dup swap @procdictkeylen idict@ abort"procedure already defined"
|
||||
1 { -rot @normal? b> <s PROC } does @doafter<{
|
||||
} : PROC:<{
|
||||
{ 0 swap @procdictkeylen idict@ not abort"`main` procedure not defined" drop
|
||||
{ over sbits < { s>c <b swap ref, b> <s } if } : @adj-long-proc
|
||||
{ // i s l
|
||||
@adj-long-proc swap @procdict @ @procdictkeylen
|
||||
idict!+ not abort"cannot define procedure, redefined?"
|
||||
@procdict !
|
||||
} : @def-proc
|
||||
{ 1000 @def-proc } : PROC
|
||||
{ 0 @def-proc } : PROCREF
|
||||
{ @procdict @ @procdictkeylen idict@ abort"procedure already defined"
|
||||
} : @fail-ifdef
|
||||
{ over @fail-ifdef
|
||||
2 { rot @normal? rot b> <s swap @def-proc drop } does
|
||||
null swap @doafter<{
|
||||
} : @PROC:<{
|
||||
{ 1000 @PROC:<{ } : PROC:<{
|
||||
{ 0 @PROC:<{ } : PROCREF:<{
|
||||
{ dup @procdict @ @procdictkeylen idict@
|
||||
{ nip INLINE } { CALLDICT } cond
|
||||
} dup : INLINECALL : INLINECALLDICT
|
||||
{ 0 @procdict @ @procdictkeylen idict@ not abort"`main` procedure not defined" drop
|
||||
} : @chkmaindef
|
||||
{ dup @chkmaindef
|
||||
{ @chkmaindef
|
||||
@proclist @ { dup null? not } {
|
||||
uncons swap dup find not
|
||||
{ +": undefined procedure name in list" abort } if
|
||||
execute 3 pick @procdictkeylen idict@ not
|
||||
execute @procdict @ @procdictkeylen idict@ not
|
||||
{ +": procedure declared but left undefined" abort } if
|
||||
drop (forget)
|
||||
} while
|
||||
drop @proclist null! @proccnt 0!
|
||||
@procdict dup @ swap null!
|
||||
} : }END
|
||||
forget @proclist forget @proccnt
|
||||
{ }END <{ SETCP0 swap @procdictkeylen DICTPUSHCONST DICTIGETJMP 11 THROWARG }> } : }END>
|
||||
|
|
|
@ -43,6 +43,9 @@ td::Result<std::string> load_TonUtil_fif(std::string dir = "") {
|
|||
td::Result<std::string> load_Lists_fif(std::string dir = "") {
|
||||
return load_source("Lists.fif", dir);
|
||||
}
|
||||
td::Result<std::string> load_Lisp_fif(std::string dir = "") {
|
||||
return load_source("Lisp.fif", dir);
|
||||
}
|
||||
|
||||
class MemoryFileLoader : public fift::FileLoader {
|
||||
public:
|
||||
|
@ -91,7 +94,8 @@ class MemoryFileLoader : public fift::FileLoader {
|
|||
};
|
||||
|
||||
td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_preamble = true, bool need_asm = true,
|
||||
bool need_ton_util = true, std::string dir = "") {
|
||||
bool need_ton_util = true, bool need_lisp = true,
|
||||
std::string dir = "") {
|
||||
auto loader = std::make_unique<MemoryFileLoader>();
|
||||
loader->add_file("/main.fif", std::move(main));
|
||||
if (need_preamble) {
|
||||
|
@ -112,6 +116,10 @@ td::Result<fift::SourceLookup> create_source_lookup(std::string main, bool need_
|
|||
loader->add_file("/TonUtil.fif", std::move(f));
|
||||
}
|
||||
}
|
||||
if (need_lisp) {
|
||||
TRY_RESULT(f, load_Lisp_fif(dir));
|
||||
loader->add_file("/Lisp.fif", std::move(f));
|
||||
}
|
||||
auto res = fift::SourceLookup(std::move(loader));
|
||||
res.add_include_path("/");
|
||||
return std::move(res);
|
||||
|
@ -143,7 +151,7 @@ td::Result<fift::SourceLookup> run_fift(fift::SourceLookup source_lookup, std::o
|
|||
} // namespace
|
||||
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args, std::string fift_dir) {
|
||||
std::stringstream ss;
|
||||
TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, fift_dir));
|
||||
TRY_RESULT(source_lookup, create_source_lookup(source, true, true, true, true, fift_dir));
|
||||
TRY_RESULT_ASSIGN(source_lookup, run_fift(std::move(source_lookup), &ss, true, std::move(args)));
|
||||
FiftOutput res;
|
||||
res.source_lookup = std::move(source_lookup);
|
||||
|
@ -159,8 +167,8 @@ td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std:
|
|||
return std::move(res);
|
||||
}
|
||||
td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::string fift_dir, bool need_preamble,
|
||||
bool need_asm, bool need_ton_util) {
|
||||
return create_source_lookup(main, need_preamble, need_asm, need_ton_util, fift_dir);
|
||||
bool need_asm, bool need_ton_util, bool need_lisp) {
|
||||
return create_source_lookup(main, need_preamble, need_asm, need_ton_util, need_lisp, fift_dir);
|
||||
}
|
||||
|
||||
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir, bool is_raw) {
|
||||
|
@ -168,7 +176,7 @@ td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_d
|
|||
TRY_RESULT(source_lookup,
|
||||
create_source_lookup(PSTRING() << "\"Asm.fif\" include\n " << (is_raw ? "<{" : "") << asm_code << "\n"
|
||||
<< (is_raw ? "}>c" : "") << " boc>B \"res\" B>file",
|
||||
true, true, true, fift_dir));
|
||||
true, true, true, false, fift_dir));
|
||||
TRY_RESULT(res, run_fift(std::move(source_lookup), &ss));
|
||||
TRY_RESULT(boc, res.read_file("res"));
|
||||
return vm::std_boc_deserialize(std::move(boc.data));
|
||||
|
|
|
@ -28,7 +28,7 @@ struct FiftOutput {
|
|||
};
|
||||
td::Result<fift::SourceLookup> create_mem_source_lookup(std::string main, std::string fift_dir = "",
|
||||
bool need_preamble = true, bool need_asm = true,
|
||||
bool need_ton_util = true);
|
||||
bool need_ton_util = true, bool need_lisp = true);
|
||||
td::Result<FiftOutput> mem_run_fift(std::string source, std::vector<std::string> args = {}, std::string fift_dir = "");
|
||||
td::Result<FiftOutput> mem_run_fift(SourceLookup source_lookup, std::vector<std::string> args);
|
||||
td::Result<td::Ref<vm::Cell>> compile_asm(td::Slice asm_code, std::string fift_dir = "", bool is_raw = true);
|
||||
|
|
|
@ -2346,7 +2346,7 @@ void compile_one_literal(WordList& wlist, vm::StackEntry val) {
|
|||
auto x = std::move(val).as_int();
|
||||
if (!x->signed_fits_bits(257)) {
|
||||
throw IntError{"invalid numeric literal"};
|
||||
} else if (x->signed_fits_bits(64)) {
|
||||
} else if (x->signed_fits_bits(td::BigIntInfo::word_shift)) {
|
||||
wlist.push_back(Ref<StackWord>{true, std::bind(interpret_const, _1, x->to_long())});
|
||||
} else {
|
||||
wlist.push_back(Ref<StackWord>{true, std::bind(interpret_big_const, _1, std::move(x))});
|
||||
|
|
|
@ -193,21 +193,21 @@ void AsmOp::out(std::ostream& os) const {
|
|||
os << (b ? "SWAP" : "NOP");
|
||||
break;
|
||||
}
|
||||
os << "s" << a << " s" << b << " XCHG";
|
||||
os << SReg(a) << ' ' << SReg(b) << " XCHG";
|
||||
break;
|
||||
case a_push:
|
||||
if (!(a & -2)) {
|
||||
os << (a ? "OVER" : "DUP");
|
||||
break;
|
||||
}
|
||||
os << "s" << a << " PUSH";
|
||||
os << SReg(a) << " PUSH";
|
||||
break;
|
||||
case a_pop:
|
||||
if (!(a & -2)) {
|
||||
os << (a ? "NIP" : "DROP");
|
||||
break;
|
||||
}
|
||||
os << "s" << a << " POP";
|
||||
os << SReg(a) << " POP";
|
||||
break;
|
||||
default:
|
||||
throw src::Fatal{"unknown assembler operation"};
|
||||
|
|
|
@ -406,8 +406,11 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
}
|
||||
func->compile(stack.o, res, args); // compile res := f (args)
|
||||
} else {
|
||||
auto fv = dynamic_cast<const SymValCodeFunc*>(fun_ref->value);
|
||||
std::string name = sym::symbols.get_name(fun_ref->sym_idx);
|
||||
stack.o << AsmOp::Custom(name + " CALLDICT", (int)right.size(), (int)left.size());
|
||||
bool is_inline = (fv && (fv->flags & 3));
|
||||
stack.o << AsmOp::Custom(name + (is_inline ? " INLINECALLDICT" : " CALLDICT"), (int)right.size(),
|
||||
(int)left.size());
|
||||
}
|
||||
}
|
||||
stack.s.resize(k);
|
||||
|
@ -553,7 +556,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
stack.opt_show();
|
||||
stack.s.pop_back();
|
||||
stack.modified();
|
||||
if (!next->is_empty()) {
|
||||
if (true || !next->is_empty()) {
|
||||
stack.o << "REPEAT:<{";
|
||||
stack.o.indent();
|
||||
stack.forget_const();
|
||||
|
@ -601,7 +604,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
case _Until: {
|
||||
// stack.drop_vars_except(block0->var_info);
|
||||
// stack.opt_show();
|
||||
if (!next->is_empty()) {
|
||||
if (true || !next->is_empty()) {
|
||||
stack.o << "UNTIL:<{";
|
||||
stack.o.indent();
|
||||
stack.forget_const();
|
||||
|
@ -632,7 +635,7 @@ bool Op::generate_code_step(Stack& stack) {
|
|||
stack.drop_vars_except(block0->var_info);
|
||||
stack.opt_show();
|
||||
StackLayout layout1 = stack.vars();
|
||||
bool next_empty = next->is_empty();
|
||||
bool next_empty = false && next->is_empty();
|
||||
stack.o << "WHILE:<{";
|
||||
stack.o.indent();
|
||||
stack.forget_const();
|
||||
|
|
|
@ -83,7 +83,8 @@ void generate_output_func(SymDef* func_sym) {
|
|||
if (verbosity >= 2) {
|
||||
std::cerr << "\n---------- resulting code for " << name << " -------------\n";
|
||||
}
|
||||
*outs << std::string(indent * 2, ' ') << name << " PROC:<{\n";
|
||||
bool inline_ref = (func_val->flags & 2);
|
||||
*outs << std::string(indent * 2, ' ') << name << " PROC" << (inline_ref ? "REF" : "") << ":<{\n";
|
||||
code.generate_code(
|
||||
*outs,
|
||||
(stack_layout_comments ? Stack::_StkCmt | Stack::_CptStkCmt : 0) | (opt_level < 2 ? Stack::_DisableOpt : 0),
|
||||
|
|
|
@ -79,6 +79,9 @@ enum Keyword {
|
|||
_RshiftLet,
|
||||
_RshiftRLet,
|
||||
_RshiftCLet,
|
||||
_AndLet,
|
||||
_OrLet,
|
||||
_XorLet,
|
||||
_Int,
|
||||
_Cell,
|
||||
_Slice,
|
||||
|
@ -90,6 +93,8 @@ enum Keyword {
|
|||
_Asm,
|
||||
_Impure,
|
||||
_Extern,
|
||||
_Inline,
|
||||
_InlineRef,
|
||||
_MethodId,
|
||||
_Operator,
|
||||
_Infix,
|
||||
|
@ -632,6 +637,9 @@ struct CodeBlob {
|
|||
}
|
||||
bool import_params(FormalArgList arg_list);
|
||||
var_idx_t create_var(int cls, TypeExpr* var_type = 0, SymDef* sym = 0, const SrcLocation* loc = 0);
|
||||
var_idx_t create_tmp_var(TypeExpr* var_type = 0, const SrcLocation* loc = 0) {
|
||||
return create_var(TmpVar::_Tmp, var_type, nullptr, loc);
|
||||
}
|
||||
int split_vars(bool strict = false);
|
||||
bool compute_used_code_vars();
|
||||
bool compute_used_code_vars(std::unique_ptr<Op>& ops, const VarDescrList& var_info, bool edit) const;
|
||||
|
@ -670,8 +678,9 @@ struct SymVal : sym::SymValBase {
|
|||
TypeExpr* sym_type;
|
||||
td::RefInt256 method_id;
|
||||
bool impure;
|
||||
short flags; // +1 = inline, +2 = inline_ref
|
||||
SymVal(int _type, int _idx, TypeExpr* _stype = nullptr, bool _impure = false)
|
||||
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure) {
|
||||
: sym::SymValBase(_type, _idx), sym_type(_stype), impure(_impure), flags(0) {
|
||||
}
|
||||
~SymVal() override = default;
|
||||
TypeExpr* get_type() const {
|
||||
|
@ -802,6 +811,10 @@ struct Expr {
|
|||
int define_new_vars(CodeBlob& code);
|
||||
int predefine_vars();
|
||||
std::vector<var_idx_t> pre_compile(CodeBlob& code) const;
|
||||
var_idx_t new_tmp(CodeBlob& code) const;
|
||||
std::vector<var_idx_t> new_tmp_vect(CodeBlob& code) const {
|
||||
return {new_tmp(code)};
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -212,6 +212,10 @@ int Expr::predefine_vars() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
var_idx_t Expr::new_tmp(CodeBlob& code) const {
|
||||
return code.create_tmp_var(e_type, &here);
|
||||
}
|
||||
|
||||
std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
|
||||
switch (cls) {
|
||||
case _Tuple: {
|
||||
|
@ -241,8 +245,7 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
|
|||
res.insert(res.end(), add.cbegin(), add.cend());
|
||||
}
|
||||
}
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto& op = code.emplace_back(here, Op::_Call, rvect, std::move(res), sym);
|
||||
if (flags & _IsImpure) {
|
||||
op.flags |= Op::_Impure;
|
||||
|
@ -256,57 +259,52 @@ std::vector<var_idx_t> Expr::pre_compile(CodeBlob& code) const {
|
|||
return {val};
|
||||
case _VarApply:
|
||||
if (args[0]->cls == _Glob) {
|
||||
std::vector<var_idx_t> res = args[1]->pre_compile(code);
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
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);
|
||||
if (args[0]->flags & _IsImpure) {
|
||||
op.flags |= Op::_Impure;
|
||||
}
|
||||
return rvect;
|
||||
} else {
|
||||
std::vector<var_idx_t> res = args[1]->pre_compile(code);
|
||||
std::vector<var_idx_t> tfunc = args[0]->pre_compile(code);
|
||||
auto res = args[1]->pre_compile(code);
|
||||
auto tfunc = args[0]->pre_compile(code);
|
||||
if (tfunc.size() != 1) {
|
||||
throw src::Fatal{"stack tuple used as a function"};
|
||||
}
|
||||
res.push_back(tfunc[0]);
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
code.emplace_back(here, Op::_CallInd, rvect, std::move(res));
|
||||
return rvect;
|
||||
}
|
||||
case _Const: {
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
code.emplace_back(here, Op::_IntConst, rvect, intval);
|
||||
return rvect;
|
||||
}
|
||||
case _Glob: {
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
code.emplace_back(here, Op::_GlobVar, rvect, std::vector<var_idx_t>{}, sym);
|
||||
return rvect;
|
||||
}
|
||||
case _Letop: {
|
||||
std::vector<var_idx_t> right = args[1]->pre_compile(code);
|
||||
std::vector<var_idx_t> left = args[0]->pre_compile(code);
|
||||
code.emplace_back(here, Op::_Let, left, std::move(right));
|
||||
return left;
|
||||
auto right = args[1]->pre_compile(code);
|
||||
auto left = args[0]->pre_compile(code);
|
||||
code.emplace_back(here, Op::_Let, std::move(left), right);
|
||||
return right;
|
||||
}
|
||||
case _LetFirst: {
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> right = args[1]->pre_compile(code);
|
||||
std::vector<var_idx_t> left = args[0]->pre_compile(code);
|
||||
left.push_back(rv);
|
||||
auto rvect = new_tmp_vect(code);
|
||||
auto right = args[1]->pre_compile(code);
|
||||
auto left = args[0]->pre_compile(code);
|
||||
left.push_back(rvect[0]);
|
||||
code.emplace_back(here, Op::_Let, std::move(left), std::move(right));
|
||||
return std::vector<var_idx_t>{rv};
|
||||
return rvect;
|
||||
}
|
||||
case _CondExpr: {
|
||||
auto cond = args[0]->pre_compile(code);
|
||||
assert(cond.size() == 1);
|
||||
var_idx_t rv = code.create_var(TmpVar::_Tmp, e_type, nullptr, &here);
|
||||
std::vector<var_idx_t> rvect{rv};
|
||||
auto rvect = new_tmp_vect(code);
|
||||
Op& if_op = code.emplace_back(here, Op::_If, cond);
|
||||
code.push_set_cur(if_op.block0);
|
||||
code.emplace_back(here, Op::_Let, rvect, args[1]->pre_compile(code));
|
||||
|
|
|
@ -79,7 +79,10 @@ void define_keywords() {
|
|||
.add_keyword("<<=", Kw::_LshiftLet)
|
||||
.add_keyword(">>=", Kw::_RshiftLet)
|
||||
.add_keyword(">>~=", Kw::_RshiftRLet)
|
||||
.add_keyword(">>^=", Kw::_RshiftCLet);
|
||||
.add_keyword(">>^=", Kw::_RshiftCLet)
|
||||
.add_keyword("&=", Kw::_AndLet)
|
||||
.add_keyword("|=", Kw::_OrLet)
|
||||
.add_keyword("^=", Kw::_XorLet);
|
||||
|
||||
sym::symbols.add_keyword("return", Kw::_Return)
|
||||
.add_keyword("var", Kw::_Var)
|
||||
|
@ -105,6 +108,8 @@ void define_keywords() {
|
|||
sym::symbols.add_keyword("extern", Kw::_Extern)
|
||||
.add_keyword("asm", Kw::_Asm)
|
||||
.add_keyword("impure", Kw::_Impure)
|
||||
.add_keyword("inline", Kw::_Inline)
|
||||
.add_keyword("inline_ref", Kw::_InlineRef)
|
||||
.add_keyword("method_id", Kw::_MethodId)
|
||||
.add_keyword("operator", Kw::_Operator)
|
||||
.add_keyword("infix", Kw::_Infix)
|
||||
|
|
|
@ -428,7 +428,6 @@ Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
|
||||
res->deduce_type(lex.cur());
|
||||
if (modify) {
|
||||
// FIXME (use _LetFirst instead of _Letop)
|
||||
auto tmp = res;
|
||||
res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}};
|
||||
res->here = loc;
|
||||
|
@ -587,7 +586,8 @@ Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) {
|
|||
auto x = parse_expr13(lex, code, nv);
|
||||
int t = lex.tp();
|
||||
if (t == _PlusLet || t == _MinusLet || t == _TimesLet || t == _DivLet || t == _DivRLet || t == _DivCLet ||
|
||||
t == _ModLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || t == _RshiftRLet) {
|
||||
t == _ModLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet || t == _RshiftRLet || t == _AndLet ||
|
||||
t == _OrLet || t == _XorLet) {
|
||||
x->chk_lvalue(lex.cur());
|
||||
x->chk_rvalue(lex.cur());
|
||||
sym_idx_t name = symbols.lookup_add(std::string{"^_"} + lex.cur().str + "_");
|
||||
|
@ -974,6 +974,11 @@ void parse_func_def(Lexer& lex) {
|
|||
if (impure) {
|
||||
lex.next();
|
||||
}
|
||||
int f = 0;
|
||||
if (lex.tp() == _Inline || lex.tp() == _InlineRef) {
|
||||
f = (lex.tp() == _Inline) ? 1 : 2;
|
||||
lex.next();
|
||||
}
|
||||
td::RefInt256 method_id;
|
||||
std::string method_name;
|
||||
if (lex.tp() == _MethodId) {
|
||||
|
@ -1071,6 +1076,17 @@ void parse_func_def(Lexer& lex) {
|
|||
lex.cur().error("integer method identifier for `"s + func_name.str + "` changed to a different value");
|
||||
}
|
||||
}
|
||||
if (f) {
|
||||
auto val = dynamic_cast<SymVal*>(func_sym->value);
|
||||
if (!val) {
|
||||
lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline");
|
||||
}
|
||||
if (!(val->flags & 3)) {
|
||||
val->flags = (short)(val->flags | f);
|
||||
} else if ((val->flags & 3) != f) {
|
||||
lex.cur().error("inline mode for `"s + func_name.str + "` changed with respect to a previous declaration");
|
||||
}
|
||||
}
|
||||
if (verbosity >= 1) {
|
||||
std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl;
|
||||
}
|
||||
|
|
20
crypto/func/test/b3.fc
Normal file
20
crypto/func/test/b3.fc
Normal file
|
@ -0,0 +1,20 @@
|
|||
;; inline test
|
||||
_ unpack() inline {
|
||||
var ds = get_data().begin_parse();
|
||||
var res = (ds~load_uint(8), ds~load_int(32), ds~load_int(32));
|
||||
return res;
|
||||
}
|
||||
|
||||
() pack(a, x, y) impure inline_ref {
|
||||
set_data(begin_cell()
|
||||
.store_uint(a, 8)
|
||||
.store_int(x, 32)
|
||||
.store_int(y, 32)
|
||||
.end_cell());
|
||||
}
|
||||
|
||||
() main() impure {
|
||||
var (a, x, y) = unpack();
|
||||
x += y;
|
||||
pack(a, x, y);
|
||||
}
|
9
crypto/func/test/w1.fc
Normal file
9
crypto/func/test/w1.fc
Normal file
|
@ -0,0 +1,9 @@
|
|||
(int, int) nested_if(int id) method_id {
|
||||
dump_stack();
|
||||
if (id > 0) {
|
||||
if (id > 10) {
|
||||
return (2 * id, 3 * id);
|
||||
}
|
||||
}
|
||||
return (5, 6);
|
||||
}
|
14
crypto/func/test/w2.fc
Normal file
14
crypto/func/test/w2.fc
Normal file
|
@ -0,0 +1,14 @@
|
|||
_ f(cs) {
|
||||
return (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8),
|
||||
cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8));
|
||||
}
|
||||
|
||||
_ main(cs) {
|
||||
var (x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10,
|
||||
x11, x12, x13, x14, x15, x16, x17, x18, x19) = f(cs);
|
||||
return x0 + x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9
|
||||
+ x10 + x11 + x12 + x13 + x14 + x15 + x16 + x17 + x18 + x19;
|
||||
}
|
2
crypto/smartcont/highload-wallet-v2.fif
Normal file → Executable file
2
crypto/smartcont/highload-wallet-v2.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <subwallet-id> <order-file> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/highload-wallet.fif
Normal file → Executable file
2
crypto/smartcont/highload-wallet.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <subwallet-id> <seqno> <order-file> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/new-highload-wallet-v2.fif
Normal file → Executable file
2
crypto/smartcont/new-highload-wallet-v2.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
|
|
2
crypto/smartcont/new-highload-wallet.fif
Normal file → Executable file
2
crypto/smartcont/new-highload-wallet.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
|
|
2
crypto/smartcont/new-pinger.fif
Normal file → Executable file
2
crypto/smartcont/new-pinger.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
|
|
2
crypto/smartcont/new-testgiver.fif
Normal file → Executable file
2
crypto/smartcont/new-testgiver.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
|
|
2
crypto/smartcont/new-wallet-v2.fif
Normal file → Executable file
2
crypto/smartcont/new-wallet-v2.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
|
|
2
crypto/smartcont/new-wallet.fif
Normal file → Executable file
2
crypto/smartcont/new-wallet.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
|
||||
|
|
2
crypto/smartcont/recover-stake.fif
Normal file → Executable file
2
crypto/smartcont/recover-stake.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/show-addr.fif
Normal file → Executable file
2
crypto/smartcont/show-addr.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base>" cr
|
||||
|
|
2
crypto/smartcont/testgiver.fif
Normal file → Executable file
2
crypto/smartcont/testgiver.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <dest-addr> <seqno> <amount> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/update-config-smc.fif
Normal file → Executable file
2
crypto/smartcont/update-config-smc.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/update-config.fif
Normal file → Executable file
2
crypto/smartcont/update-config.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <seqno> <index> <new-value-boc> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/update-elector-smc.fif
Normal file → Executable file
2
crypto/smartcont/update-elector-smc.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <seqno> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/validator-elect-req.fif
Normal file → Executable file
2
crypto/smartcont/validator-elect-req.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <wallet-addr> <elect-utime> <max-factor> <adnl-addr> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/validator-elect-signed.fif
Normal file → Executable file
2
crypto/smartcont/validator-elect-signed.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <wallet-addr> <elect-utime> <max-factor> <adnl-addr> <validator-pubkey> <validator-signature> [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/wallet-v2.fif
Normal file → Executable file
2
crypto/smartcont/wallet-v2.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <seqno> <amount> [-B <body-boc>] [<savefile>]" cr
|
||||
|
|
2
crypto/smartcont/wallet.fif
Normal file → Executable file
2
crypto/smartcont/wallet.fif
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env fift -s
|
||||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
|
||||
{ ."usage: " @' $0 type ." <filename-base> <dest-addr> <seqno> <amount> [-B <body-boc>] [-C <transfer-comment>] [<savefile>]" cr
|
||||
|
|
|
@ -90,3 +90,23 @@ TEST(Fift, test) {
|
|||
TEST(Fift, bug_div) {
|
||||
run_fift("bug_div.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, bug_ufits) {
|
||||
run_fift("bug_ufits.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_dict) {
|
||||
run_fift("testdict.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_fixed) {
|
||||
run_fift("fixed.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_sort) {
|
||||
run_fift("sort.fif");
|
||||
}
|
||||
|
||||
TEST(Fift, test_sort2) {
|
||||
run_fift("sort2.fif");
|
||||
}
|
||||
|
|
1
crypto/test/fift/bug_ufits.fif
Normal file
1
crypto/test/fift/bug_ufits.fif
Normal file
|
@ -0,0 +1 @@
|
|||
100000000000000000 dup =: amount 56 ufits . amount 56 ufits .
|
Loading…
Add table
Add a link
Reference in a new issue