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