// if(x) then ... else ... void TrFun_If::CompileDeclaration( PM_Automat &pm, lem::Iridium::Macro_Parser &txtfile, TrFunctions &functions, TrKnownVars &known_vars, const TrBuiltInFunSignature *signature ) { src_location = pm.GetDict().GetDebugSymbols().RegisterLocation( txtfile, txtfile.tellp() ); // ”словие опционально может быть заключено в круглые скобочки. const bool req_paren = txtfile.probe( B_OROUNDPAREN ); cond = functions.CompileCall( pm, txtfile, known_vars ); if( req_paren ) txtfile.read_it( B_CROUNDPAREN ); txtfile.read_it( B_THEN ); f_then = functions.CompileCall( pm, txtfile, known_vars ); txtfile.probe( B_SEMICOLON ); if( txtfile.pick().GetToken()==B_ELSE ) { txtfile.read_it(B_ELSE); f_else = functions.CompileCall( pm, txtfile, known_vars ); txtfile.probe( B_SEMICOLON ); } return; }
void TrFun_Declare::CompileDeclaration( PM_Automat &pm, lem::Iridium::Macro_Parser &txtfile, TrFunctions &functions, const TrProcedureDeclaration &procs, TrKnownVars &known_vars, const TrBuiltInFunSignature *signature ) { src_location = pm.GetDict().GetDebugSymbols().RegisterLocation( txtfile, txtfile.tellp() ); var_type.LoadTxt(pm,txtfile,functions); while( !txtfile.eof() ) { TrFunCall *expr = NULL; const lem::Iridium::BethToken &vname = txtfile.read(); if( txtfile.pick().GetToken()==B_EQUAL ) { txtfile.read(); expr = functions.CompileCall( pm, txtfile, procs, known_vars ); } if( var_name.find(vname.string())!=UNKNOWN ) { lem::Iridium::Print_Error( vname, txtfile ); pm.GetIO().merr().printf( "Variable [%us] is already declared", vname.c_str() ); throw E_ParserError(); } var_name.push_back(vname); var_value.push_back(expr); known_vars.RegisterVar( var_type, vname ); if( txtfile.pick().GetToken()!=B_COMMA ) break; txtfile.read_it(B_COMMA); } txtfile.read_it(B_SEMICOLON); return; }
void TrFunction::CompileDeclaration( PM_Automat &pm, lem::Iridium::Macro_Parser &txtfile, TrFunctions &functions, const TrProcedureDeclaration &procs, const TrKnownVars *lambda_caller ) { const bool is_lambda = lambda_caller!=NULL; lem::Iridium::BSourceState fun_beg = txtfile.tellp(); ret_type.LoadTxt( pm, txtfile, functions ); lem::Iridium::BSourceState ss = txtfile.tellp(); try { if( is_lambda ) { // Формируем "невозможное" имя лямбда-функции, которое наверняка не будет // пересекаться с пользовательскими и встроенными функциями. static int lambda_number=0; name = L" $lambda"; name += to_ustr(lambda_number++); } else { name = txtfile.read(); } if( pm.GetDict().GetDebugLevel_ir()>=3 ) { // Печатаем имя транслируемой статьи для контроля за процессом // парсинга Словаря. pm.GetDict().GetIO().mecho().printf( "function [%vfA%us%vn]->", name.c_str() ); } if( !is_lambda && !CorrectName(name) ) { lem::Iridium::Print_Error( ss, txtfile ); pm.GetIO().merr().printf( "Invalid function name [%us]\n", name.c_str() ); throw E_ParserError(); } txtfile.read_it( B_OROUNDPAREN ); TrKnownVars call_vars( lambda_caller==NULL ? &functions.global_known_vars : lambda_caller ); // Список формальных аргументов while( !txtfile.eof() ) { if( txtfile.pick().GetToken()==B_CROUNDPAREN ) break; if( arg_name.size()>0 ) txtfile.read_it(B_COMMA); TrType at; at.LoadTxt(pm,txtfile,functions); const lem::Iridium::BethToken &an = txtfile.read(); if( arg_name.find(an)!=UNKNOWN ) { lem::Iridium::Print_Error( an, txtfile ); pm.GetIO().merr().printf( "Function [%us] call argument [%us] is already declared\n", name.c_str(), an.string().c_str() ); throw E_ParserError(); } arg_type.push_back(at); arg_name.push_back(an.string()); call_vars.RegisterVar( at, an.string() ); } txtfile.read_it( B_CROUNDPAREN ); if( txtfile.pick().GetToken()==B_SEMICOLON ) { txtfile.read(); // Это форвардное объявление функции, без определения тела. } else { // Чтобы компилировать рекурсивные функции, мы сейчас добавим в список функций свое форвардное объявление. if( !is_lambda && !functions.IsFunction(name) ) { TrFunction *forward = MakeForwardDeclaration(); functions.AddForwardDeclaration(forward); } // В фигурных скобочках - тело функции. Оно компилируется как вызов специальной функции-группы {} txtfile.read_it( B_OFIGPAREN ); txtfile.backward(); body = functions.CompileCall( pm, txtfile, procs, call_vars ); } if( pm.GetDict().GetDebugLevel_ir()>=3 ) pm.GetIO().mecho().printf( "%vfAOK%vn\n" ); } catch(...) { lem::Iridium::Print_Error( ss, txtfile ); pm.GetIO().merr().printf( "Error in function [%us] definition\n", name.c_str() ); throw; } return; }
void TrFun_Lambda::Link( const TrFunctions &funs ) { fun = funs.Find(name); body = &*fun->body; return; }