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

[Tolk] Implement AST: intermediate representation of tolk files

Now, the whole .tolk file can be loaded as AST tree and
then converted to Expr/Op.
This gives a great ability to implement AST transformations.
In the future, more and more code analysis will be moved out of legacy to AST-level.
This commit is contained in:
tolk-vm 2024-10-31 11:03:33 +04:00
parent 6c30e5a7eb
commit 80001d1756
No known key found for this signature in database
GPG key ID: 7905DD7FE0324B12
23 changed files with 3798 additions and 2233 deletions

View file

@ -41,19 +41,7 @@ Expr::Expr(ExprCls c, sym_idx_t name_idx, std::initializer_list<Expr*> _arglist)
}
}
void Expr::chk_rvalue(const Lexer& lex) const {
if (!is_rvalue()) {
lex.error_at("rvalue expected before `", "`");
}
}
void Expr::chk_lvalue(const Lexer& lex) const {
if (!is_lvalue()) {
lex.error_at("lvalue expected before `", "`");
}
}
bool Expr::deduce_type(const Lexer& lex) {
bool Expr::deduce_type() {
if (e_type) {
return true;
}
@ -77,7 +65,7 @@ bool Expr::deduce_type(const Lexer& lex) {
std::ostringstream os;
os << "cannot apply function " << sym->name() << " : " << sym_val->get_type() << " to arguments of type "
<< fun_type->args[0] << ": " << ue;
lex.error(os.str());
throw ParseError(here, os.str());
}
e_type = fun_type->args[1];
TypeExpr::remove_indirect(e_type);
@ -92,7 +80,7 @@ bool Expr::deduce_type(const Lexer& lex) {
std::ostringstream os;
os << "cannot apply expression of type " << args[0]->e_type << " to an expression of type " << args[1]->e_type
<< ": " << ue;
lex.error(os.str());
throw ParseError(here, os.str());
}
e_type = fun_type->args[1];
TypeExpr::remove_indirect(e_type);
@ -107,7 +95,7 @@ bool Expr::deduce_type(const Lexer& lex) {
std::ostringstream os;
os << "cannot assign an expression of type " << args[1]->e_type << " to a variable or pattern of type "
<< args[0]->e_type << ": " << ue;
lex.error(os.str());
throw ParseError(here, os.str());
}
e_type = args[0]->e_type;
TypeExpr::remove_indirect(e_type);
@ -124,7 +112,7 @@ bool Expr::deduce_type(const Lexer& lex) {
os << "cannot implicitly assign an expression of type " << args[1]->e_type
<< " to a variable or pattern of type " << rhs_type << " in modifying method `" << G.symbols.get_name(val)
<< "` : " << ue;
lex.error(os.str());
throw ParseError(here, os.str());
}
e_type = rhs_type->args[1];
TypeExpr::remove_indirect(e_type);
@ -139,7 +127,7 @@ bool Expr::deduce_type(const Lexer& lex) {
} catch (UnifyError& ue) {
std::ostringstream os;
os << "condition in a conditional expression has non-integer type " << args[0]->e_type << ": " << ue;
lex.error(os.str());
throw ParseError(here, os.str());
}
try {
unify(args[1]->e_type, args[2]->e_type);
@ -147,7 +135,7 @@ bool Expr::deduce_type(const Lexer& lex) {
std::ostringstream os;
os << "the two variants in a conditional expression have different types " << args[1]->e_type << " and "
<< args[2]->e_type << " : " << ue;
lex.error(os.str());
throw ParseError(here, os.str());
}
e_type = args[1]->e_type;
TypeExpr::remove_indirect(e_type);
@ -170,13 +158,13 @@ int Expr::define_new_vars(CodeBlob& code) {
}
case _Var:
if (val < 0) {
val = code.create_var(TmpVar::_Named, e_type, sym, here);
val = code.create_var(false, e_type, sym, here);
return 1;
}
break;
case _Hole:
if (val < 0) {
val = code.create_var(TmpVar::_Tmp, e_type, nullptr, here);
val = code.create_var(true, e_type, nullptr, here);
}
break;
}
@ -279,7 +267,7 @@ std::vector<var_idx_t> pre_compile_tensor(const std::vector<Expr *>& args, CodeB
res_lists[i] = args[i]->pre_compile(code, lval_globs);
for (size_t j = 0; j < res_lists[i].size(); ++j) {
TmpVar& var = code.vars.at(res_lists[i][j]);
if (!lval_globs && (var.cls & TmpVar::_Named)) {
if (!lval_globs && !var.is_tmp_unnamed) {
var.on_modification.push_back([&modified_vars, i, j, cur_ops = code.cur_ops, done = false](SrcLocation here) mutable {
if (!done) {
done = true;