11#include < fstream>
22#include < iostream>
33#include < map>
4+ #include < set>
45#include < memory>
56#include < string>
67#include < cmath>
@@ -2843,7 +2844,6 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> {
28432844 bool current_procedure_interface = false ;
28442845 bool overload = false ;
28452846 bool vectorize = false , is_inline = false , is_static = false ;
2846-
28472847 Vec<ASR::ttype_t *> tps;
28482848 tps.reserve (al, x.m_args .n_args );
28492849 bool is_restriction = false ;
@@ -2866,6 +2866,8 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> {
28662866 vectorize = true ;
28672867 } else if (name == " restriction" ) {
28682868 is_restriction = true ;
2869+ } else if (name == " with_goto" ) {
2870+ // TODO: Use goto attribute in function?
28692871 } else if (name == " inline" ) {
28702872 is_inline = true ;
28712873 } else if (name == " static" ) {
@@ -3211,11 +3213,14 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
32113213
32123214public:
32133215 ASR::asr_t *asr;
3216+ std::map<std::string, std::tuple<int64_t , bool , Location>> goto_name2id;
3217+ int64_t gotoids;
32143218
32153219
32163220 BodyVisitor (Allocator &al, ASR::asr_t *unit, diag::Diagnostics &diagnostics,
32173221 bool main_module, std::map<int , ASR::symbol_t *> &ast_overload)
3218- : CommonVisitor(al, nullptr , diagnostics, main_module, ast_overload, " " ), asr{unit}
3222+ : CommonVisitor(al, nullptr , diagnostics, main_module, ast_overload, " " ), asr{unit},
3223+ gotoids{0 }
32193224 {}
32203225
32213226 // Transforms statements to a list of ASR statements
@@ -3300,6 +3305,8 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
33003305 }
33013306
33023307 void visit_FunctionDef (const AST::FunctionDef_t &x) {
3308+ goto_name2id.clear ();
3309+ gotoids = 0 ;
33033310 SymbolTable *old_scope = current_scope;
33043311 ASR::symbol_t *t = current_scope->get_symbol (x.m_name );
33053312 if (ASR::is_a<ASR::Function_t>(*t)) {
@@ -3320,6 +3327,13 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
33203327 }
33213328 current_scope = old_scope;
33223329 tmp = nullptr ;
3330+
3331+ for ( auto itr: goto_name2id ) {
3332+ if ( !std::get<1 >(itr.second ) ) {
3333+ throw SemanticError (" Label '" + itr.first + " ' is not defined in '"
3334+ + std::string (x.m_name ) + " '" , std::get<2 >(itr.second ));
3335+ }
3336+ }
33233337 }
33243338
33253339 void visit_Import (const AST::Import_t &/* x*/ ) {
@@ -3969,7 +3983,36 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
39693983 void visit_Attribute (const AST::Attribute_t &x) {
39703984 if (AST::is_a<AST::Name_t>(*x.m_value )) {
39713985 std::string value = AST::down_cast<AST::Name_t>(x.m_value )->m_id ;
3986+ if ( value == " label" ) {
3987+ std::string labelname = x.m_attr ;
3988+ if ( goto_name2id.find (labelname) == goto_name2id.end () ) {
3989+ goto_name2id[labelname] = std::make_tuple (gotoids, true , x.base .base .loc );
3990+ gotoids += 1 ;
3991+ } else if ( !std::get<1 >(goto_name2id[labelname]) ) {
3992+ goto_name2id[labelname] = std::make_tuple (
3993+ std::get<0 >(goto_name2id[labelname]),
3994+ true ,
3995+ std::get<2 >(goto_name2id[labelname])
3996+ );
3997+ }
3998+ int id = std::get<0 >(goto_name2id[labelname]);
3999+ tmp = ASR::make_GoToTarget_t (al, x.base .base .loc , id, x.m_attr );
4000+ return ;
4001+ }
4002+
4003+ if (value == " goto" ){
4004+ std::string labelname = std::string (x.m_attr );
4005+ if ( goto_name2id.find (labelname) == goto_name2id.end () ) {
4006+ goto_name2id[labelname] = std::make_tuple (gotoids, false , x.base .base .loc );
4007+ gotoids += 1 ;
4008+ }
4009+ int id = std::get<0 >(goto_name2id[labelname]);
4010+ tmp = ASR::make_GoTo_t (al, x.base .base .loc , id, x.m_attr );
4011+ return ;
4012+ }
4013+
39724014 ASR::symbol_t *t = current_scope->resolve_symbol (value);
4015+
39734016 if (!t) {
39744017 throw SemanticError (" '" + value + " ' is not defined in the scope" ,
39754018 x.base .base .loc );
@@ -4543,8 +4586,14 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
45434586 return ;
45444587 }
45454588 this ->visit_expr (*x.m_value );
4546- ASRUtils::EXPR (tmp);
4547- tmp = nullptr ;
4589+
4590+ // If tmp is a statement and not an expression
4591+ // never cast into expression using ASRUtils::EXPR
4592+ // Just ignore and exit the function naturally.
4593+ if ( !ASR::is_a<ASR::stmt_t >(*tmp) ) {
4594+ LFORTRAN_ASSERT (ASR::is_a<ASR::expr_t >(*tmp));
4595+ tmp = nullptr ;
4596+ }
45484597 }
45494598
45504599
0 commit comments