mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
[Tolk] Compiler built-in __expect_type()
for testing purposes
Currently, tolk-tester can test various "output" of the compiler: pass input and check output, validate fif codegen, etc. But it can not test compiler internals and AST representation. I've added an ability to have special functions to check/expose internal compiler state. The first (and the only now) is: > __expect_type(some_expr, "<type>"); Such a call has special treatment in a compilation process. Compilation fails if this expression doesn't have requested type. It's intended to be used in tests only. Not present in stdlib.
This commit is contained in:
parent
c720204199
commit
989629a832
9 changed files with 147 additions and 7 deletions
|
@ -1255,6 +1255,13 @@ void define_builtins() {
|
|||
define_builtin_func("debugDumpStack", {}, Unit, nullptr,
|
||||
AsmOp::Custom("DUMPSTK", 0, 0),
|
||||
0);
|
||||
|
||||
// functions not presented in stdlib at all
|
||||
// used in tolk-tester to check/expose internal compiler state
|
||||
// each of them is handled in a special way, search by its name
|
||||
define_builtin_func("__expect_type", {TypeDataUnknown::create(), Slice}, Unit, nullptr,
|
||||
AsmOp::Nop(),
|
||||
FunctionData::flagMarkedAsPure);
|
||||
}
|
||||
|
||||
} // namespace tolk
|
||||
|
|
|
@ -555,6 +555,15 @@ Lexer::Lexer(const SrcFile* file)
|
|||
next();
|
||||
}
|
||||
|
||||
Lexer::Lexer(std::string_view text)
|
||||
: file(nullptr)
|
||||
, p_start(text.data())
|
||||
, p_end(p_start + text.size())
|
||||
, p_next(p_start)
|
||||
, location() {
|
||||
next();
|
||||
}
|
||||
|
||||
void Lexer::next() {
|
||||
while (cur_token_idx == last_token_idx && !is_eof()) {
|
||||
update_location();
|
||||
|
@ -563,7 +572,7 @@ void Lexer::next() {
|
|||
}
|
||||
}
|
||||
if (is_eof()) {
|
||||
add_token(tok_eof, file->text);
|
||||
add_token(tok_eof, "");
|
||||
}
|
||||
cur_token = tokens_circularbuf[++cur_token_idx & 7];
|
||||
}
|
||||
|
|
|
@ -173,6 +173,7 @@ public:
|
|||
};
|
||||
|
||||
explicit Lexer(const SrcFile* file);
|
||||
explicit Lexer(std::string_view text);
|
||||
Lexer(const Lexer&) = delete;
|
||||
Lexer &operator=(const Lexer&) = delete;
|
||||
|
||||
|
|
|
@ -240,6 +240,24 @@ public:
|
|||
TypePtr get_result() const { return unified_result; }
|
||||
};
|
||||
|
||||
// handle __expect_type(expr, "type") call
|
||||
// this is used in compiler tests
|
||||
GNU_ATTRIBUTE_NOINLINE GNU_ATTRIBUTE_COLD
|
||||
static void handle_possible_compiler_internal_call(const FunctionData* current_function, V<ast_function_call> v) {
|
||||
const FunctionData* fun_ref = v->fun_maybe;
|
||||
tolk_assert(fun_ref && fun_ref->is_builtin_function());
|
||||
static_cast<void>(current_function);
|
||||
|
||||
if (fun_ref->name == "__expect_type") {
|
||||
tolk_assert(v->get_num_args() == 2);
|
||||
TypePtr expected_type = parse_type_from_string(v->get_arg(1)->get_expr()->as<ast_string_const>()->str_val);
|
||||
TypePtr expr_type = v->get_arg(0)->inferred_type;
|
||||
if (expected_type != expr_type) {
|
||||
v->error("__expect_type failed: expected " + to_string(expected_type) + ", got " + to_string(expr_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This class handles all types of AST vertices and traverses them, filling all AnyExprV::inferred_type.
|
||||
* Note, that it isn't derived from ASTVisitor, it has manual `switch` over all existing vertex types.
|
||||
|
@ -974,6 +992,9 @@ class InferCheckTypesAndCallsAndFieldsVisitor final {
|
|||
TypePtr inferred_type = dot_obj && fun_ref->does_return_self() ? dot_obj->inferred_type : fun_ref->inferred_return_type;
|
||||
assign_inferred_type(v, inferred_type);
|
||||
assign_inferred_type(callee, fun_ref->inferred_full_type);
|
||||
if (fun_ref->is_builtin_function() && fun_ref->name[0] == '_') {
|
||||
handle_possible_compiler_internal_call(current_function, v);
|
||||
}
|
||||
// note, that mutate params don't affect typing, they are handled when converting to IR
|
||||
}
|
||||
|
||||
|
|
|
@ -651,11 +651,6 @@ static TypePtr parse_simple_type(Lexer& lex) {
|
|||
std::vector<TypePtr> items = parse_nested_type_list(lex, tok_opbracket, "`[`", tok_clbracket, "`]` or `,`");
|
||||
return TypeDataTypedTuple::create(std::move(items));
|
||||
}
|
||||
case tok_fun: {
|
||||
lex.next();
|
||||
std::vector<TypePtr> params_types = parse_nested_type_list_in_parenthesis(lex);
|
||||
lex.expect(tok_arrow, "`->`");
|
||||
}
|
||||
default:
|
||||
lex.unexpected("<type>");
|
||||
}
|
||||
|
@ -695,6 +690,12 @@ TypePtr parse_type_from_tokens(Lexer& lex) {
|
|||
return parse_type_expression(lex);
|
||||
}
|
||||
|
||||
// for internal usage only
|
||||
TypePtr parse_type_from_string(std::string_view text) {
|
||||
Lexer lex(text);
|
||||
return parse_type_expression(lex);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, TypePtr type_data) {
|
||||
return os << (type_data ? type_data->as_human_readable() : "(nullptr-type)");
|
||||
}
|
||||
|
|
|
@ -417,6 +417,7 @@ public:
|
|||
|
||||
class Lexer;
|
||||
TypePtr parse_type_from_tokens(Lexer& lex);
|
||||
TypePtr parse_type_from_string(std::string_view text);
|
||||
|
||||
void type_system_init();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue