--- parser3/src/main/execute.C 2002/04/18 11:41:29 1.237 +++ parser3/src/main/execute.C 2002/04/22 10:32:30 1.240 @@ -4,7 +4,7 @@ Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) - $Id: execute.C,v 1.237 2002/04/18 11:41:29 paf Exp $ + $Id: execute.C,v 1.240 2002/04/22 10:32:30 paf Exp $ */ #include "pa_opcode.h" @@ -111,6 +111,49 @@ void debug_dump(Pool& pool, int level, c #define POP_NAME() static_cast(stack.pop())->as_string() #define POP_CODE() static_cast(stack.pop()) +/** + Helps preventing evaluation of junctions in outdated context + + To stop situations like this: +@code + @main[] + ^method1[] + ^method2[] + + @method1[] + $junction{ + some code + } + + @method2[] + ^junction[] +@endcode + + All Junctions, generated by OP_CURLY_CODE__CONSTRUCT are registered here, + and on scope exit got cleaned - there Junction::root becomes 0, + which later in Request::process triggers exception +*/ +class Auto_junction_cleaner { +public: + Auto_junction_cleaner () : junctions(0) {} + ~Auto_junction_cleaner () { + if(junctions) { + Array_iter i(*junctions); + while(i.has_next()) + static_cast(i.next())->change_context(0); + // someday free junctions + } + } + void register_junction(Pool& apool, Junction& ajunction) { + if(!junctions) + junctions=new(apool) Array(apool); + if(junctions) + *junctions+=&ajunction; + } +private: + Array *junctions; +}; + void Request::execute(const Array& ops) { // _asm int 3; #ifdef DEBUG_EXECUTE @@ -119,6 +162,7 @@ void Request::execute(const Array& ops) debug_printf(pool(), "execution-------------------------\n"); #endif + Auto_junction_cleaner junction_cleaner; const String *last_get_element_name=0; Array_iter i(ops); @@ -214,7 +258,8 @@ void Request::execute(const Array& ops) rcontext, wcontext, local_ops); - + junction_cleaner.register_junction(pool(), j); + value=NEW VJunction(j); const String& name=POP_NAME(); Value *ncontext=POP(); @@ -859,6 +904,12 @@ StringOrValue Request::process(Value& in #ifdef DEBUG_EXECUTE debug_printf(pool(), "ja->\n"); #endif + + if(!junction->root) + throw Exception("parser.runtime", + 0, + "junction used outside of context"); + PUSH(self); PUSH(root); PUSH(rcontext);