/* 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 "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}; } }; 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