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

[Tolk] Get rid of ~tilda with mutate and self methods

This is a very big change.
If FunC has `.methods()` and `~methods()`, Tolk has only dot,
one and only way to call a `.method()`.
A method may mutate an object, or may not.
It's a behavioral and semantic difference from FunC.

- `cs.loadInt(32)` modifies a slice and returns an integer
- `b.storeInt(x, 32)` modifies a builder
- `b = b.storeInt()` also works, since it not only modifies, but returns
- chained methods also work, they return `self`
- everything works exactly as expected, similar to JS
- no runtime overhead, exactly same Fift instructions
- custom methods are created with ease
- tilda `~` does not exist in Tolk at all
This commit is contained in:
tolk-vm 2024-10-31 11:18:54 +04:00
parent 12ff28ac94
commit d9dba320cc
No known key found for this signature in database
GPG key ID: 7905DD7FE0324B12
85 changed files with 2710 additions and 1965 deletions

View file

@ -68,11 +68,14 @@ enum ASTNodeType {
ast_string_const,
ast_bool_const,
ast_null_keyword,
ast_self_keyword,
ast_argument,
ast_argument_list,
ast_function_call,
ast_dot_method_call,
ast_global_var_declaration,
ast_constant_declaration,
ast_underscore,
ast_dot_tilde_call,
ast_unary_operator,
ast_binary_operator,
ast_ternary_operator,
@ -285,13 +288,50 @@ struct Vertex<ast_null_keyword> final : ASTNodeLeaf {
};
template<>
struct Vertex<ast_function_call> final : ASTNodeBinary {
// even for f(1,2,3), f (lhs) is called with a single arg (tensor "(1,2,3)") (rhs)
AnyV get_called_f() const { return lhs; }
auto get_called_arg() const { return rhs->as<ast_tensor>(); }
struct Vertex<ast_self_keyword> final : ASTNodeLeaf {
explicit Vertex(SrcLocation loc)
: ASTNodeLeaf(ast_self_keyword, loc) {}
};
Vertex(SrcLocation loc, AnyV lhs_f, V<ast_tensor> arg)
: ASTNodeBinary(ast_function_call, loc, lhs_f, arg) {}
template<>
struct Vertex<ast_argument> final : ASTNodeUnary {
bool passed_as_mutate; // when called `f(mutate arg)`, not `f(arg)`
AnyV get_expr() const { return child; }
explicit Vertex(SrcLocation loc, AnyV expr, bool passed_as_mutate)
: ASTNodeUnary(ast_argument, loc, expr), passed_as_mutate(passed_as_mutate) {}
};
template<>
struct Vertex<ast_argument_list> final : ASTNodeVararg {
const std::vector<AnyV>& get_arguments() const { return children; }
auto get_arg(int i) const { return children.at(i)->as<ast_argument>(); }
explicit Vertex(SrcLocation loc, std::vector<AnyV> arguments)
: ASTNodeVararg(ast_argument_list, loc, std::move(arguments)) {}
};
template<>
struct Vertex<ast_function_call> final : ASTNodeBinary {
AnyV get_called_f() const { return lhs; }
auto get_arg_list() const { return rhs->as<ast_argument_list>(); }
int get_num_args() const { return rhs->as<ast_argument_list>()->size(); }
auto get_arg(int i) const { return rhs->as<ast_argument_list>()->get_arg(i); }
Vertex(SrcLocation loc, AnyV lhs_f, V<ast_argument_list> arguments)
: ASTNodeBinary(ast_function_call, loc, lhs_f, arguments) {}
};
template<>
struct Vertex<ast_dot_method_call> final : ASTNodeBinary {
std::string_view method_name;
AnyV get_obj() const { return lhs; }
auto get_arg_list() const { return rhs->as<ast_argument_list>(); }
Vertex(SrcLocation loc, std::string_view method_name, AnyV lhs, V<ast_argument_list> arguments)
: ASTNodeBinary(ast_dot_method_call, loc, lhs, arguments), method_name(method_name) {}
};
template<>
@ -321,17 +361,6 @@ struct Vertex<ast_underscore> final : ASTNodeLeaf {
: ASTNodeLeaf(ast_underscore, loc) {}
};
template<>
struct Vertex<ast_dot_tilde_call> final : ASTNodeBinary {
std::string_view method_name; // starts with . or ~
AnyV get_lhs() const { return lhs; }
auto get_arg() const { return rhs->as<ast_tensor>(); }
Vertex(SrcLocation loc, std::string_view method_name, AnyV lhs, V<ast_tensor> arg)
: ASTNodeBinary(ast_dot_tilde_call, loc, lhs, arg), method_name(method_name) {}
};
template<>
struct Vertex<ast_unary_operator> final : ASTNodeUnary {
std::string_view operator_name;
@ -475,11 +504,13 @@ struct Vertex<ast_genericsT_list> final : ASTNodeVararg {
template<>
struct Vertex<ast_parameter> final : ASTNodeUnary {
TypeExpr* param_type;
bool declared_as_mutate; // declared as `mutate param_name`
auto get_identifier() const { return child->as<ast_identifier>(); } // for underscore, its str_val is empty
auto get_identifier() const { return child->as<ast_identifier>(); } // for underscore, name is empty
bool is_underscore() const { return child->as<ast_identifier>()->name.empty(); }
Vertex(SrcLocation loc, V<ast_identifier> name_identifier, TypeExpr* param_type)
: ASTNodeUnary(ast_parameter, loc, name_identifier), param_type(param_type) {}
Vertex(SrcLocation loc, V<ast_identifier> name_identifier, TypeExpr* param_type, bool declared_as_mutate)
: ASTNodeUnary(ast_parameter, loc, name_identifier), param_type(param_type), declared_as_mutate(declared_as_mutate) {}
};
template<>
@ -491,6 +522,8 @@ struct Vertex<ast_parameter_list> final : ASTNodeVararg {
: ASTNodeVararg(ast_parameter_list, loc, std::move(params)) {}
int lookup_idx(std::string_view param_name) const;
int get_mutate_params_count() const;
bool has_mutate_params() const { return get_mutate_params_count() > 0; }
};
template<>
@ -519,12 +552,13 @@ struct Vertex<ast_annotation> final : ASTNodeUnary {
template<>
struct Vertex<ast_local_var> final : ASTNodeUnary {
TypeExpr* declared_type;
bool is_immutable; // declared via 'val', not 'var'
bool marked_as_redef; // var (existing_var redef, new_var: int) = ...
AnyV get_identifier() const { return child; } // ast_identifier / ast_underscore
Vertex(SrcLocation loc, AnyV name_identifier, TypeExpr* declared_type, bool marked_as_redef)
: ASTNodeUnary(ast_local_var, loc, name_identifier), declared_type(declared_type), marked_as_redef(marked_as_redef) {}
Vertex(SrcLocation loc, AnyV name_identifier, TypeExpr* declared_type, bool is_immutable, bool marked_as_redef)
: ASTNodeUnary(ast_local_var, loc, name_identifier), declared_type(declared_type), is_immutable(is_immutable), marked_as_redef(marked_as_redef) {}
};
template<>
@ -552,6 +586,8 @@ struct Vertex<ast_function_declaration> final : ASTNodeVararg {
bool marked_as_get_method = false;
bool marked_as_inline = false;
bool marked_as_inline_ref = false;
bool accepts_self = false;
bool returns_self = false;
V<ast_int_const> method_id = nullptr;
bool is_asm_function() const { return children.at(2)->type == ast_asm_body; }