/* This file is part of TON Blockchain Library. TON Blockchain Library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. TON Blockchain Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with TON Blockchain Library. If not, see . Copyright 2020 Telegram Systems LLP */ #pragma once #include #include "common/refcnt.hpp" #include "common/refint.h" #include "vm/stack.hpp" namespace fift { using td::Ref; struct IntCtx; /* * * FIFT CONTINUATIONS * */ class FiftCont : public td::CntObject { public: FiftCont() = default; virtual ~FiftCont() override = default; virtual Ref run_tail(IntCtx& ctx) const = 0; virtual Ref run_modify(IntCtx& ctx) { return run_tail(ctx); } virtual Ref handle_tail(IntCtx& ctx) const { return {}; } virtual Ref handle_modify(IntCtx& ctx) { return handle_tail(ctx); } virtual Ref up() const { return {}; } virtual bool is_list() const { return false; } virtual long long list_size() const { return -1; } virtual const Ref* get_list() const { return nullptr; } virtual bool is_literal() const { return false; } virtual int literal_count() const { return -1; } virtual std::vector get_literals() const { return {}; } std::string get_dict_name(const IntCtx& ctx) const; bool print_dict_name(std::ostream& os, const IntCtx& ctx) const; bool print_dummy_name(std::ostream& os, const IntCtx& ctx) const; virtual bool print_name(std::ostream& os, const IntCtx& ctx) const; virtual bool dump(std::ostream& os, const IntCtx& ctx) const; Ref self() const { return Ref{this}; } }; typedef std::function StackWordFunc; typedef std::function CtxWordFunc; typedef std::function(IntCtx&)> CtxTailWordFunc; class NopWord : public FiftCont { public: NopWord() = default; ~NopWord() override = default; Ref run_tail(IntCtx& ctx) const override { return {}; } }; class StackWord : public FiftCont { StackWordFunc f; public: StackWord(StackWordFunc _f) : f(std::move(_f)) { } ~StackWord() override = default; Ref run_tail(IntCtx& ctx) const override; }; class CtxWord : public FiftCont { CtxWordFunc f; public: CtxWord(CtxWordFunc _f) : f(std::move(_f)) { } ~CtxWord() override = default; Ref run_tail(IntCtx& ctx) const override; }; class CtxTailWord : public FiftCont { CtxTailWordFunc f; public: CtxTailWord(CtxTailWordFunc _f) : f(std::move(_f)) { } ~CtxTailWord() override = default; Ref run_tail(IntCtx& ctx) const override; }; class WordList : public FiftCont { std::vector> list; public: ~WordList() override = default; WordList() = default; WordList(std::vector>&& _list); WordList(const std::vector>& _list); WordList& push_back(Ref word_def); WordList& push_back(FiftCont& wd); Ref run_tail(IntCtx& ctx) const override; void close(); bool is_list() const override { return true; } long long list_size() const override { return (long long)list.size(); } std::size_t size() const { return list.size(); } const Ref& at(std::size_t idx) const { return list.at(idx); } const Ref* get_list() const override { return list.data(); } WordList& append(const std::vector>& other); WordList& append(const Ref* begin, const Ref* end); WordList* make_copy() const override { return new WordList(list); } bool dump(std::ostream& os, const IntCtx& ctx) const override; }; class ListCont : public FiftCont { Ref next; Ref list; std::size_t pos; public: ListCont(Ref nxt, Ref wl, std::size_t p = 0) : next(std::move(nxt)), list(std::move(wl)), pos(p) { } ~ListCont() override = default; Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; Ref up() const override { return next; } bool dump(std::ostream& os, const IntCtx& ctx) const override; }; class QuitCont : public FiftCont { int exit_code; public: QuitCont(int _exit_code = -1) : exit_code(_exit_code) { } Ref run_tail(IntCtx& ctx) const override; bool print_name(std::ostream& os, const IntCtx& ctx) const override; }; class SeqCont : public FiftCont { Ref first, second; public: SeqCont(Ref _first, Ref _second) : first(std::move(_first)), second(std::move(_second)) { } static Ref seq(Ref _first, Ref _second) { return _second.is_null() ? std::move(_first) : td::make_ref(std::move(_first), std::move(_second)); } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; Ref up() const override { return second; } bool print_name(std::ostream& os, const IntCtx& ctx) const override; bool dump(std::ostream& os, const IntCtx& ctx) const override; }; class TimesCont : public FiftCont { Ref body, after; int count; public: TimesCont(Ref _body, Ref _after, int _count) : body(std::move(_body)), after(std::move(_after)), count(_count) { } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; Ref up() const override { return after; } bool print_name(std::ostream& os, const IntCtx& ctx) const override; bool dump(std::ostream& os, const IntCtx& ctx) const override; }; class UntilCont : public FiftCont { Ref body, after; public: UntilCont(Ref _body, Ref _after) : body(std::move(_body)), after(std::move(_after)) { } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; bool print_name(std::ostream& os, const IntCtx& ctx) const override; bool dump(std::ostream& os, const IntCtx& ctx) const override; }; class WhileCont : public FiftCont { Ref cond, body, after; bool stage; public: WhileCont(Ref _cond, Ref _body, Ref _after, bool _stage = false) : cond(std::move(_cond)), body(std::move(_body)), after(std::move(_after)), stage(_stage) { } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; Ref up() const override { return after; } bool print_name(std::ostream& os, const IntCtx& ctx) const override; bool dump(std::ostream& os, const IntCtx& ctx) const override; }; class LoopCont : public FiftCont { Ref func, after; int state; public: LoopCont(Ref _func, Ref _after, int _state = 0) : func(std::move(_func)), after(std::move(_after)), state(_state) { } LoopCont(const LoopCont&) = default; virtual bool init(IntCtx& ctx) { return true; } virtual bool pre_exec(IntCtx& ctx) { return true; } virtual bool post_exec(IntCtx& ctx) { return true; } virtual bool finalize(IntCtx& ctx) { return true; } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; Ref up() const override { return after; } bool print_name(std::ostream& os, const IntCtx& ctx) const override; }; class GenericLitCont : public FiftCont { public: bool is_literal() const override { return true; } std::vector get_literals() const override = 0; bool print_name(std::ostream& os, const IntCtx& ctx) const override; }; class SmallIntLitCont : public GenericLitCont { long long value_; public: SmallIntLitCont(long long value) : value_(value) { } Ref run_tail(IntCtx& ctx) const override; std::vector get_literals() const override; static Ref literal(long long int_value) { return td::make_ref(int_value); } }; class IntLitCont : public GenericLitCont { td::RefInt256 value_; public: IntLitCont(td::RefInt256 value) : value_(std::move(value)) { } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; std::vector get_literals() const override { return {vm::StackEntry(value_)}; } static Ref literal(td::RefInt256 int_value); static Ref literal(long long int_value) { return SmallIntLitCont::literal(int_value); } }; class LitCont : public GenericLitCont { vm::StackEntry value_; public: LitCont(const vm::StackEntry& value) : value_(value) { } LitCont(vm::StackEntry&& value) : value_(std::move(value)) { } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; std::vector get_literals() const override { return {value_}; } static Ref literal(vm::StackEntry value); static Ref literal(td::RefInt256 int_value) { return IntLitCont::literal(std::move(int_value)); } static Ref literal(long long int_value) { return SmallIntLitCont::literal(int_value); } }; class MultiLitCont : public GenericLitCont { std::vector values_; public: MultiLitCont(const std::vector& values) : values_(values) { } MultiLitCont(std::vector&& values) : values_(std::move(values)) { } MultiLitCont(std::initializer_list value_list) : values_(value_list) { } Ref run_tail(IntCtx& ctx) const override; Ref run_modify(IntCtx& ctx) override; std::vector get_literals() const override { return values_; } MultiLitCont& push_back(vm::StackEntry new_literal); vm::StackEntry at(int idx) const; }; class InterpretCont : public FiftCont { public: InterpretCont() = default; Ref run_tail(IntCtx&) const override; // text interpreter, defined in words.cpp bool print_name(std::ostream& os, const IntCtx& ctx) const override { os << ""; return true; } }; } // namespace fift