1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

[Tolk] v0.6 syntax: fun, import, var, types on the right, etc.

Lots of changes, actually. Most noticeable are:
- traditional //comments
- #include -> import
- a rule "import what you use"
- ~ found -> !found (for -1/0)
- null() -> null
- is_null?(v) -> v == null
- throw is a keyword
- catch with swapped arguments
- throw_if, throw_unless -> assert
- do until -> do while
- elseif -> else if
- drop ifnot, elseifnot
- drop rarely used operators

A testing framework also appears here. All tests existed earlier,
but due to significant syntax changes, their history is useless.
This commit is contained in:
tolk-vm 2024-10-31 11:11:41 +04:00
parent 5a3e3595d6
commit e2edadba92
No known key found for this signature in database
GPG key ID: 7905DD7FE0324B12
133 changed files with 8196 additions and 2605 deletions

View file

@ -16,6 +16,7 @@
*/
#pragma once
#include "platform-utils.h"
#include "src-file.h"
#include "type-expr.h"
#include "symtable.h"
@ -26,12 +27,13 @@
#include <stack>
#include <iostream>
#define tolk_assert(expr) \
(bool(expr) ? void(0) \
: throw Fatal(PSTRING() << "Assertion failed at " << __FILE__ << ":" << __LINE__ << ": " << #expr))
#define tolk_assert(expr) if(UNLIKELY(!(expr))) on_assertion_failed(#expr, __FILE__, __LINE__);
namespace tolk {
GNU_ATTRIBUTE_COLD GNU_ATTRIBUTE_NORETURN
void on_assertion_failed(const char *description, const char *file_name, int line_number);
/*
*
* TYPE EXPRESSIONS
@ -90,27 +92,23 @@ struct VarDescr {
_NonZero = 128,
_Pos = 256,
_Neg = 512,
_Bool = 1024,
_Bit = 2048,
_Finite = 4096,
_Nan = 8192,
_Even = 16384,
_Odd = 32768,
_Null = (1 << 16),
_NotNull = (1 << 17)
};
static constexpr int ConstZero = _Int | _Zero | _Pos | _Neg | _Bool | _Bit | _Finite | _Even | _NotNull;
static constexpr int ConstOne = _Int | _NonZero | _Pos | _Bit | _Finite | _Odd | _NotNull;
static constexpr int ConstTrue = _Int | _NonZero | _Neg | _Bool | _Finite | _Odd | _NotNull;
static constexpr int ValBit = ConstZero & ConstOne;
static constexpr int ValBool = ConstZero & ConstTrue;
static constexpr int FiniteInt = _Int | _Finite | _NotNull;
static constexpr int FiniteUInt = FiniteInt | _Pos;
static constexpr int ConstZero = _Const | _Int | _Zero | _Pos | _Neg | _Finite | _Even;
static constexpr int ConstOne = _Const | _Int | _NonZero | _Pos | _Finite | _Odd;
static constexpr int ConstTrue = _Const | _Int | _NonZero | _Neg | _Finite | _Odd;
static constexpr int ValBit = _Int | _Pos | _Finite;
static constexpr int ValBool = _Int | _Neg | _Finite;
static constexpr int FiniteInt = _Int | _Finite;
static constexpr int FiniteUInt = _Int | _Finite | _Pos;
int val;
td::RefInt256 int_const;
std::string str_const;
VarDescr(var_idx_t _idx = -1, int _flags = 0, int _val = 0) : idx(_idx), flags(_flags), val(_val) {
explicit VarDescr(var_idx_t _idx = -1, int _flags = 0, int _val = 0) : idx(_idx), flags(_flags), val(_val) {
}
bool operator<(var_idx_t other_idx) const {
return idx < other_idx;
@ -139,15 +137,6 @@ struct VarDescr {
bool always_odd() const {
return val & _Odd;
}
bool always_null() const {
return val & _Null;
}
bool always_not_null() const {
return val & _NotNull;
}
bool is_const() const {
return val & _Const;
}
bool is_int_const() const {
return (val & (_Int | _Const)) == (_Int | _Const) && int_const.not_null();
}
@ -260,7 +249,7 @@ class ListIterator {
public:
ListIterator() : ptr(nullptr) {
}
ListIterator(T* _ptr) : ptr(_ptr) {
explicit ListIterator(T* _ptr) : ptr(_ptr) {
}
ListIterator& operator++() {
ptr = ptr->next.get();
@ -383,18 +372,6 @@ struct Op {
const Op& last() const {
return next ? next->last() : *this;
}
ListIterator<Op> begin() {
return ListIterator<Op>{this};
}
ListIterator<Op> end() const {
return ListIterator<Op>{};
}
ListIterator<const Op> cbegin() {
return ListIterator<const Op>{this};
}
ListIterator<const Op> cend() const {
return ListIterator<const Op>{};
}
};
inline ListIterator<Op> begin(const std::unique_ptr<Op>& op_list) {
@ -405,14 +382,6 @@ inline ListIterator<Op> end(const std::unique_ptr<Op>& op_list) {
return ListIterator<Op>{};
}
inline ListIterator<const Op> cbegin(const Op* op_list) {
return ListIterator<const Op>{op_list};
}
inline ListIterator<const Op> cend(const Op* op_list) {
return ListIterator<const Op>{};
}
inline ListIterator<const Op> begin(const Op* op_list) {
return ListIterator<const Op>{op_list};
}
@ -421,78 +390,11 @@ inline ListIterator<const Op> end(const Op* op_list) {
return ListIterator<const Op>{};
}
inline ListIterator<Op> begin(Op* op_list) {
return ListIterator<Op>{op_list};
}
inline ListIterator<Op> end(Op* op_list) {
return ListIterator<Op>{};
}
typedef std::tuple<TypeExpr*, SymDef*, SrcLocation> FormalArg;
typedef std::vector<FormalArg> FormalArgList;
struct AsmOpList;
struct CodeBlob {
enum { _ForbidImpure = 4 };
int var_cnt, in_var_cnt, op_cnt;
TypeExpr* ret_type;
std::string name;
SrcLocation loc;
std::vector<TmpVar> vars;
std::unique_ptr<Op> ops;
std::unique_ptr<Op>* cur_ops;
std::stack<std::unique_ptr<Op>*> cur_ops_stack;
int flags = 0;
bool require_callxargs = false;
CodeBlob(std::string name, SrcLocation loc, TypeExpr* ret)
: var_cnt(0), in_var_cnt(0), op_cnt(0), ret_type(ret), name(std::move(name)), loc(loc), cur_ops(&ops) {
}
template <typename... Args>
Op& emplace_back(Args&&... args) {
Op& res = *(*cur_ops = std::make_unique<Op>(args...));
cur_ops = &(res.next);
return res;
}
bool import_params(FormalArgList arg_list);
var_idx_t create_var(bool is_tmp_unnamed, TypeExpr* var_type, SymDef* sym, SrcLocation loc);
var_idx_t create_tmp_var(TypeExpr* var_type, SrcLocation loc) {
return create_var(true, 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;
void print(std::ostream& os, int flags = 0) const;
void push_set_cur(std::unique_ptr<Op>& new_cur_ops) {
cur_ops_stack.push(cur_ops);
cur_ops = &new_cur_ops;
}
void close_blk(SrcLocation location) {
*cur_ops = std::make_unique<Op>(location, Op::_Nop);
}
void pop_cur() {
cur_ops = cur_ops_stack.top();
cur_ops_stack.pop();
}
void close_pop_cur(SrcLocation location) {
close_blk(location);
pop_cur();
}
void simplify_var_types();
void prune_unreachable_code();
void fwd_analyze();
void mark_noreturn();
void generate_code(AsmOpList& out_list, int mode = 0);
void generate_code(std::ostream& os, int mode = 0, int indent = 0);
void on_var_modification(var_idx_t idx, SrcLocation here) const {
for (auto& f : vars.at(idx).on_modification) {
f(here);
}
}
};
/*
*
* SYMBOL VALUES
@ -512,13 +414,14 @@ struct SymVal : SymValBase {
struct SymValFunc : SymVal {
enum SymValFlag {
flagInline = 1, // function marked `inline`
flagInlineRef = 2, // function marked `inline_ref`
flagWrapsAnotherF = 4, // (T) thisF(...args) { return anotherF(...args); } (calls to thisF will be replaced)
flagInline = 1, // marked `@inline`
flagInlineRef = 2, // marked `@inline_ref`
flagWrapsAnotherF = 4, // `fun thisF(...args) { return anotherF(...args); }` (calls to thisF will be inlined)
flagUsedAsNonCall = 8, // used not only as `f()`, but as a 1-st class function (assigned to var, pushed to tuple, etc.)
flagMarkedAsPure = 16, // declared as `pure`, can't call impure and access globals, unused invocations are optimized out
flagBuiltinFunction = 32, // was created via `define_builtin_func()`, not from source code
flagGetMethod = 64, // was declared via `get T func()`, method_id is auto-assigned
flagGetMethod = 64, // was declared via `get func(): T`, method_id is auto-assigned
flagIsEntrypoint = 128, // it's `main` / `onExternalMessage` / etc.
};
td::RefInt256 method_id; // todo why int256? it's small
@ -559,6 +462,9 @@ struct SymValFunc : SymVal {
bool is_get_method() const {
return flags & flagGetMethod;
}
bool is_entrypoint() const {
return flags & flagIsEntrypoint;
}
};
struct SymValCodeFunc : SymValFunc {
@ -626,7 +532,6 @@ struct Expr {
_None,
_Apply,
_VarApply,
_TypeApply,
_MkTuple,
_Tensor,
_Const,
@ -636,13 +541,12 @@ struct Expr {
_Letop,
_LetFirst,
_Hole,
_Type,
_CondExpr,
_SliceConst,
};
ExprCls cls;
int val{0};
enum { _IsType = 1, _IsRvalue = 2, _IsLvalue = 4, _IsImpure = 32 };
enum { _IsRvalue = 2, _IsLvalue = 4, _IsImpure = 32 };
int flags{0};
SrcLocation here;
td::RefInt256 intval;
@ -681,12 +585,6 @@ struct Expr {
bool is_lvalue() const {
return flags & _IsLvalue;
}
bool is_type() const {
return flags & _IsType;
}
bool is_type_apply() const {
return cls == _TypeApply;
}
bool is_mktuple() const {
return cls == _MkTuple;
}
@ -1449,6 +1347,65 @@ struct SymValAsmFunc : SymValFunc {
bool compile(AsmOpList& dest, std::vector<VarDescr>& out, std::vector<VarDescr>& in, SrcLocation where) const;
};
struct CodeBlob {
enum { _ForbidImpure = 4 };
int var_cnt, in_var_cnt, op_cnt;
TypeExpr* ret_type;
std::string name;
SrcLocation loc;
std::vector<TmpVar> vars;
std::unique_ptr<Op> ops;
std::unique_ptr<Op>* cur_ops;
std::stack<std::unique_ptr<Op>*> cur_ops_stack;
int flags = 0;
bool require_callxargs = false;
CodeBlob(std::string name, SrcLocation loc, TypeExpr* ret)
: var_cnt(0), in_var_cnt(0), op_cnt(0), ret_type(ret), name(std::move(name)), loc(loc), cur_ops(&ops) {
}
template <typename... Args>
Op& emplace_back(Args&&... args) {
Op& res = *(*cur_ops = std::make_unique<Op>(args...));
cur_ops = &(res.next);
return res;
}
bool import_params(FormalArgList arg_list);
var_idx_t create_var(bool is_tmp_unnamed, TypeExpr* var_type, SymDef* sym, SrcLocation loc);
var_idx_t create_tmp_var(TypeExpr* var_type, SrcLocation loc) {
return create_var(true, 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;
void print(std::ostream& os, int flags = 0) const;
void push_set_cur(std::unique_ptr<Op>& new_cur_ops) {
cur_ops_stack.push(cur_ops);
cur_ops = &new_cur_ops;
}
void close_blk(SrcLocation location) {
*cur_ops = std::make_unique<Op>(location, Op::_Nop);
}
void pop_cur() {
cur_ops = cur_ops_stack.top();
cur_ops_stack.pop();
}
void close_pop_cur(SrcLocation location) {
close_blk(location);
pop_cur();
}
void simplify_var_types();
void prune_unreachable_code();
void fwd_analyze();
void mark_noreturn();
void generate_code(AsmOpList& out_list, int mode = 0);
void generate_code(std::ostream& os, int mode = 0, int indent = 0);
void on_var_modification(var_idx_t idx, SrcLocation here) const {
for (auto& f : vars.at(idx).on_modification) {
f(here);
}
}
};
// defined in builtins.cpp
AsmOp exec_arg_op(std::string op, long long arg);
AsmOp exec_arg_op(std::string op, long long arg, int args, int retv = 1);