mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
Add pragmas to funC for precise control of computation order (#589)
* FunC pragmas: allow-post-modification and compute-asm-ltr * Warn if #pragma is enabled only in included files * Add tests for new pragmas * Add special ops for "allow-post-modification" only when needed * Update FunC version to 0.4.1 * Allow empty inlines (#10) Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
parent
6b49d6a382
commit
653c88aa9d
8 changed files with 344 additions and 61 deletions
|
@ -261,6 +261,12 @@ void parse_const_decl(Lexer& lex) {
|
|||
}
|
||||
lex.next();
|
||||
CodeBlob code;
|
||||
if (pragma_allow_post_modification.enabled()) {
|
||||
code.flags |= CodeBlob::_AllowPostModification;
|
||||
}
|
||||
if (pragma_compute_asm_ltr.enabled()) {
|
||||
code.flags |= CodeBlob::_ComputeAsmLtr;
|
||||
}
|
||||
// Handles processing and resolution of literals and consts
|
||||
auto x = parse_expr(lex, code, false); // also does lex.next() !
|
||||
if (x->flags != Expr::_IsRvalue) {
|
||||
|
@ -1210,6 +1216,12 @@ blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code) {
|
|||
CodeBlob* parse_func_body(Lexer& lex, FormalArgList arg_list, TypeExpr* ret_type) {
|
||||
lex.expect('{');
|
||||
CodeBlob* blob = new CodeBlob{ret_type};
|
||||
if (pragma_allow_post_modification.enabled()) {
|
||||
blob->flags |= CodeBlob::_AllowPostModification;
|
||||
}
|
||||
if (pragma_compute_asm_ltr.enabled()) {
|
||||
blob->flags |= CodeBlob::_ComputeAsmLtr;
|
||||
}
|
||||
blob->import_params(std::move(arg_list));
|
||||
blk_fl::val res = blk_fl::init;
|
||||
bool warned = false;
|
||||
|
@ -1676,6 +1688,10 @@ void parse_pragma(Lexer& lex) {
|
|||
}
|
||||
func_ver_test = lex.cur().str;
|
||||
lex.next();
|
||||
} else if (pragma_name == pragma_allow_post_modification.name()) {
|
||||
pragma_allow_post_modification.enable(lex.cur().loc);
|
||||
} else if (pragma_name == pragma_compute_asm_ltr.name()) {
|
||||
pragma_compute_asm_ltr.enable(lex.cur().loc);
|
||||
} else {
|
||||
lex.cur().error(std::string{"unknown pragma `"} + pragma_name + "`");
|
||||
}
|
||||
|
@ -1684,7 +1700,7 @@ void parse_pragma(Lexer& lex) {
|
|||
|
||||
std::vector<const src::FileDescr*> source_fdescr;
|
||||
|
||||
std::vector<std::string> source_files;
|
||||
std::map<std::string, src::FileDescr*> source_files;
|
||||
std::stack<src::SrcLocation> inclusion_locations;
|
||||
|
||||
void parse_include(Lexer& lex, const src::FileDescr* fdescr) {
|
||||
|
@ -1700,7 +1716,7 @@ void parse_include(Lexer& lex, const src::FileDescr* fdescr) {
|
|||
}
|
||||
lex.next();
|
||||
lex.expect(';');
|
||||
if (!parse_source_file(val.c_str(), include)) {
|
||||
if (!parse_source_file(val.c_str(), include, false)) {
|
||||
include.error(std::string{"failed parsing included file `"} + val + "`");
|
||||
}
|
||||
}
|
||||
|
@ -1724,7 +1740,7 @@ bool parse_source(std::istream* is, src::FileDescr* fdescr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool parse_source_file(const char* filename, src::Lexem lex) {
|
||||
bool parse_source_file(const char* filename, src::Lexem lex, bool is_main) {
|
||||
if (!filename || !*filename) {
|
||||
auto msg = "source file name is an empty string";
|
||||
if (lex.tp) {
|
||||
|
@ -1741,7 +1757,9 @@ bool parse_source_file(const char* filename, src::Lexem lex) {
|
|||
return false;
|
||||
}
|
||||
std::string real_filename = path_res.move_as_ok();
|
||||
if (std::count(source_files.begin(), source_files.end(), real_filename)) {
|
||||
auto it = source_files.find(real_filename);
|
||||
if (it != source_files.end()) {
|
||||
it->second->is_main |= is_main;
|
||||
if (verbosity >= 2) {
|
||||
if (lex.tp) {
|
||||
lex.loc.show_warning(std::string{"skipping file "} + real_filename + " because it was already included");
|
||||
|
@ -1755,8 +1773,9 @@ bool parse_source_file(const char* filename, src::Lexem lex) {
|
|||
funC::generated_from += std::string{"incl:"};
|
||||
}
|
||||
funC::generated_from += std::string{"`"} + filename + "` ";
|
||||
source_files.push_back(real_filename);
|
||||
src::FileDescr* cur_source = new src::FileDescr{filename};
|
||||
source_files[real_filename] = cur_source;
|
||||
cur_source->is_main = is_main;
|
||||
source_fdescr.push_back(cur_source);
|
||||
std::ifstream ifs{filename};
|
||||
if (ifs.fail()) {
|
||||
|
@ -1775,6 +1794,7 @@ bool parse_source_file(const char* filename, src::Lexem lex) {
|
|||
|
||||
bool parse_source_stdin() {
|
||||
src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
|
||||
cur_source->is_main = true;
|
||||
source_fdescr.push_back(cur_source);
|
||||
return parse_source(&std::cin, cur_source);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue