• R/O
  • SSH
  • HTTPS

eircompile: Commit


Commit MetaInfo

Revision61 (tree)
Time2021-12-18 02:40:23
Authorquiret

Log Message

- added denial-inheritance-guarantee optimization for the lexer which improves object take-over in case that denial of changes by word rejection by sub-steps is pushed through to the step where working-copy data has originated from, effectively rejecting the data; this eradicates data copies for sequences inside of sequences in many cases (one is used in the standard compilation syntax so this optimization is a must-have)
- added SCS grammar for the replacement-point-step + unit test
- added an unit test for the new optimization strategy

Change Summary

Incremental Difference

--- eircompile/include/eircompile/lexing_compile.h (revision 60)
+++ eircompile/include/eircompile/lexing_compile.h (revision 61)
@@ -139,6 +139,15 @@
139139 typename cenv_t::StepSeparation seqextpt_extlist = &cenv;
140140 typename cenv_t::SerializedStep seqextpt = &cenv;
141141
142+ typename cenv_t::StepToken tok_equal = &cenv;
143+ typename cenv_t::StepToken tok_replpt_begin = &cenv;
144+ //tok_replpt_end = tok_cbrackets_end
145+ //typename cenv_t::StepAttribution seqreplpt_replitem_key = &cenv;
146+ typename cenv_t::StepAttribution seqreplpt_replitem_value = &cenv;
147+ typename cenv_t::SerializedStep seqreplpt_replitem = &cenv;
148+ typename cenv_t::StepSeparation seqreplpt_repllist = &cenv;
149+ typename cenv_t::SerializedStep seqreplpt = &cenv;
150+
142151 typename cenv_t::StepToken tok_procalts_beg = &cenv;
143152 //tok_procalts_end = tok_cbrackets_end
144153 typename cenv_t::StepSeparation seqprocalts_itemsep = &cenv;
@@ -165,6 +174,7 @@
165174 typename cenv_t::StepToken tokinline = &cenv;
166175 typename cenv_t::StepToken tokextended = &cenv;
167176 typename cenv_t::StepToken tokprocgate = &cenv;
177+ typename cenv_t::StepToken tokreplaceable = &cenv;
168178 typename cenv_t::StepAlternatives callprodattrib = &cenv;
169179 typename cenv_t::SerializedStep callprodattrib_spacesappend = &cenv;
170180 typename cenv_t::StepRepeatByInterval opt_callprodattrib = &cenv;
@@ -174,6 +184,127 @@
174184
175185 typedef LexingPoint <charType> LexingPoint;
176186
187+ struct replpt_selector
188+ {
189+ inline replpt_selector( LexingCompiler *env ) noexcept : env( env )
190+ {
191+ if ( auto *runtime_env = env->runtime_env )
192+ {
193+ auto *replpt = runtime_env->CreateStep <typename compileForEnvType::StepReplacementPoint> ();
194+
195+ replpt->AddStackRef();
196+
197+ this->replpt = replpt;
198+ }
199+ else
200+ {
201+ this->replpt = nullptr;
202+ }
203+ }
204+ inline replpt_selector( const replpt_selector& right ) : env( right.env )
205+ {
206+ if ( auto *replpt = right.replpt )
207+ {
208+ auto *newReplpt = (typename compileForEnvType::StepReplacementPoint*)replpt->Clone();
209+
210+ this->replpt = newReplpt;
211+
212+ newReplpt->AddStackRef();
213+ }
214+ else
215+ {
216+ this->replpt = nullptr;
217+ }
218+
219+ this->curKeyNode = right.curKeyNode;
220+ }
221+ inline replpt_selector( replpt_selector&& right ) noexcept : env( right.env )
222+ {
223+ this->replpt = right.replpt;
224+ this->curKeyNode = right.curKeyNode;
225+
226+ right.replpt = nullptr;
227+ right.curKeyNode = nullptr;
228+ }
229+
230+ inline ~replpt_selector( void )
231+ {
232+ if ( auto *replpt = this->replpt )
233+ {
234+ replpt->Delete();
235+ }
236+ }
237+
238+ inline void AssignAttribute( const eir::FixedString <charType>& attrib, const eir::FixedString <charType>& value )
239+ {
240+ auto *replpt = this->replpt;
241+
242+ if ( replpt == nullptr )
243+ return;
244+
245+ if ( attrib == _AttribKey_CallToken <charType> () )
246+ {
247+#ifdef _DEBUG
248+ assert( this->curKeyNode == nullptr );
249+#endif //_DEBUG
250+
251+ auto *runtime_env = this->env->runtime_env;
252+
253+ this->curKeyNode = &runtime_env->nonterminal_namespace.get( value, runtime_env );
254+ return;
255+ }
256+ }
257+
258+ inline bool AssignNode( const eir::FixedString <charType>& attrib, ExecStep *node )
259+ {
260+ auto *replpt = this->replpt;
261+
262+ if ( replpt == nullptr )
263+ {
264+ return false;
265+ }
266+
267+ if ( replpt->GetNode() == nullptr )
268+ {
269+ replpt->SetNode( node );
270+ return true;
271+ }
272+ if ( attrib == _AttribKey_Value <charType> () )
273+ {
274+ ExecStep *curKeyNode = this->curKeyNode;
275+
276+#ifdef _DEBUG
277+ assert( curKeyNode != nullptr );
278+#endif //_DEBUG
279+
280+ this->curKeyNode = nullptr;
281+
282+ replpt->SetReplacement( curKeyNode, node );
283+ return true;
284+ }
285+
286+ return false;
287+ }
288+
289+ inline ExecStep* DetachFinishedNode( void )
290+ {
291+ auto *replpt = this->replpt;
292+
293+ if ( replpt )
294+ {
295+ replpt->RemStackRef();
296+
297+ this->replpt = nullptr;
298+ }
299+
300+ return replpt;
301+ }
302+
303+ LexingCompiler *env;
304+ typename compileForEnvType::StepReplacementPoint *replpt;
305+ ExecStep *curKeyNode = nullptr; // actually a production alternative coming from the environment, safe ref.
306+ };
307+
177308 template <typename... allocArgs> requires ( eir::constructible_from <allocatorType, allocArgs...> )
178309 LexingCompiler( eir::constr_with_alloc _, allocArgs&&... args )
179310 : cenv( std::tuple <allocArgs&&...> ( std::forward <allocArgs> ( args )... ), std::tuple( this ) )
@@ -745,6 +876,48 @@
745876
746877 safe_enclosed_prod.AddConnection( &seqextpt );
747878
879+ // *** REPLACEMENT-POINT STEP ***
880+
881+ // &( exec, p1=n1, ..., pn=nn )
882+ tok_equal.token_str = _Token_Equal <charType> ();
883+
884+ tok_replpt_begin.token_str = _Token_Ampersand <charType> ();
885+ tok_replpt_begin.token_str += _Token_CurlyBrackets_Begin <charType> ();
886+
887+ //seqreplpt_replitem_key.SetNode( &prodtoken );
888+ //seqreplpt_replitem_key.attribute_key = _AttribKey_Key <charType> ();
889+
890+ seqreplpt_replitem_value.SetNode( &producible_procgate );
891+ seqreplpt_replitem_value.attribute_key = _AttribKey_Value <charType> ();
892+
893+ seqreplpt_replitem.SetConnections( {
894+ &prodtoken,
895+ &spaces,
896+ &tok_equal,
897+ &spaces,
898+ &seqreplpt_replitem_value
899+ } );
900+
901+ seqreplpt_repllist.SetItemStep( &seqreplpt_replitem );
902+ seqreplpt_repllist.SetSeparationStep( &spaced_comma_tok );
903+ seqreplpt_repllist.min_item_cnt = 1;
904+ seqreplpt_repllist.is_alternation = false;
905+
906+ seqreplpt.SetConnections( {
907+ &tok_replpt_begin,
908+ &spaces,
909+ &producible_procgate,
910+ &spaced_comma_tok,
911+ &seqreplpt_repllist,
912+ &spaces,
913+ &tok_cbrackets_end
914+ } );
915+
916+ // see above for definition of replpt_selector.
917+ seqreplpt.setSelector <replpt_selector> ( this );
918+
919+ safe_enclosed_prod.AddConnection( &seqreplpt );
920+
748921 // *** PROCEDURAL ALTERNATIVES STEP ***
749922
750923 // $( p1, ..., pn )
@@ -1053,10 +1226,13 @@
10531226
10541227 tokprocgate.token_str = _Token_Procgate <charType> ();
10551228
1229+ tokreplaceable.token_str = _Token_Replaceable <charType> ();
1230+
10561231 callprodattrib.SetConnections( {
10571232 &tokinline,
10581233 &tokextended,
1059- &tokprocgate
1234+ &tokprocgate,
1235+ &tokreplaceable
10601236 } );
10611237 callprodattrib.attribute_key = _AttribKey_Attribute <charType> ();
10621238
@@ -1064,7 +1240,7 @@
10641240
10651241 opt_callprodattrib.min_rep_cnt = 0;
10661242 opt_callprodattrib.has_maximum = true;
1067- opt_callprodattrib.max_rep_cnt = 3;
1243+ opt_callprodattrib.max_rep_cnt = 4;
10681244 opt_callprodattrib.SetNode( &callprodattrib_spacesappend );
10691245
10701246 callprod.SetConnections( { &opt_callprodattrib, &prodtoken } );
@@ -1146,7 +1322,7 @@
11461322 template <eir::CharacterType charType>
11471323 static AINLINE bool IsProductionCharacter( charType ucp )
11481324 {
1149- static const char validchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1325+ static const char validchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-";
11501326
11511327 for ( char c : validchars )
11521328 {
@@ -1351,6 +1527,56 @@
13511527 }
13521528
13531529 template <eir::CharacterType charType>
1530+ static AINLINE const charType* _AttribKey_Key( void ) noexcept
1531+ {
1532+ if constexpr ( std::same_as <charType, char> )
1533+ {
1534+ return "key";
1535+ }
1536+ if constexpr ( std::same_as <charType, wchar_t> )
1537+ {
1538+ return L"key";
1539+ }
1540+ if constexpr ( std::same_as <charType, char8_t> )
1541+ {
1542+ return u8"key";
1543+ }
1544+ if constexpr ( std::same_as <charType, char16_t> )
1545+ {
1546+ return u"key";
1547+ }
1548+ if constexpr ( std::same_as <charType, char32_t> )
1549+ {
1550+ return U"key";
1551+ }
1552+ }
1553+
1554+ template <eir::CharacterType charType>
1555+ static AINLINE const charType* _AttribKey_Value( void ) noexcept
1556+ {
1557+ if constexpr ( std::same_as <charType, char> )
1558+ {
1559+ return "value";
1560+ }
1561+ if constexpr ( std::same_as <charType, wchar_t> )
1562+ {
1563+ return L"value";
1564+ }
1565+ if constexpr ( std::same_as <charType, char8_t> )
1566+ {
1567+ return u8"value";
1568+ }
1569+ if constexpr ( std::same_as <charType, char16_t> )
1570+ {
1571+ return u"value";
1572+ }
1573+ if constexpr ( std::same_as <charType, char32_t> )
1574+ {
1575+ return U"value";
1576+ }
1577+ }
1578+
1579+ template <eir::CharacterType charType>
13541580 static AINLINE const charType* _AttribKey_ProductionNode( void ) noexcept
13551581 {
13561582 if constexpr ( std::same_as <charType, char> )
@@ -1748,6 +1974,30 @@
17481974 return U"procgate";
17491975 }
17501976 }
1977+ template <eir::CharacterType charType>
1978+ static AINLINE const charType* _Token_Replaceable( void ) noexcept
1979+ {
1980+ if constexpr ( std::same_as <charType, char> )
1981+ {
1982+ return "replaceable";
1983+ }
1984+ if constexpr ( std::same_as <charType, wchar_t> )
1985+ {
1986+ return L"replaceable";
1987+ }
1988+ if constexpr ( std::same_as <charType, char8_t> )
1989+ {
1990+ return u8"replaceable";
1991+ }
1992+ if constexpr ( std::same_as <charType, char16_t> )
1993+ {
1994+ return u"replaceable";
1995+ }
1996+ if constexpr ( std::same_as <charType, char32_t> )
1997+ {
1998+ return U"replaceable";
1999+ }
2000+ }
17512001
17522002 template <eir::CharacterType charType>
17532003 static AINLINE const charType* _Token_TakeFirst( void ) noexcept
@@ -1800,6 +2050,56 @@
18002050 }
18012051
18022052 template <eir::CharacterType charType>
2053+ static AINLINE const charType* _Token_Equal( void ) noexcept
2054+ {
2055+ if constexpr ( std::same_as <charType, char> )
2056+ {
2057+ return "=";
2058+ }
2059+ if constexpr ( std::same_as <charType, wchar_t> )
2060+ {
2061+ return L"=";
2062+ }
2063+ if constexpr ( std::same_as <charType, char8_t> )
2064+ {
2065+ return u8"=";
2066+ }
2067+ if constexpr ( std::same_as <charType, char16_t> )
2068+ {
2069+ return u"=";
2070+ }
2071+ if constexpr ( std::same_as <charType, char32_t> )
2072+ {
2073+ return U"=";
2074+ }
2075+ }
2076+
2077+ template <eir::CharacterType charType>
2078+ static AINLINE const charType* _Token_Ampersand( void ) noexcept
2079+ {
2080+ if constexpr ( std::same_as <charType, char> )
2081+ {
2082+ return "&";
2083+ }
2084+ if constexpr ( std::same_as <charType, wchar_t> )
2085+ {
2086+ return L"&";
2087+ }
2088+ if constexpr ( std::same_as <charType, char8_t> )
2089+ {
2090+ return u8"&";
2091+ }
2092+ if constexpr ( std::same_as <charType, char16_t> )
2093+ {
2094+ return u"&";
2095+ }
2096+ if constexpr ( std::same_as <charType, char32_t> )
2097+ {
2098+ return U"&";
2099+ }
2100+ }
2101+
2102+ template <eir::CharacterType charType>
18032103 static AINLINE const charType* _Token_SeparationIsAlternation( void ) noexcept
18042104 {
18052105 if constexpr ( std::same_as <charType, char> )
@@ -2203,6 +2503,10 @@
22032503 {
22042504 this->is_procedural_gate = true;
22052505 }
2506+ else if ( prodName == _Token_Replaceable <charType> () )
2507+ {
2508+ this->replaceable = true;
2509+ }
22062510 }
22072511 }
22082512 };
--- eircompile/include/eircompile/lexing_env.h (revision 60)
+++ eircompile/include/eircompile/lexing_env.h (revision 61)
@@ -564,6 +564,10 @@
564564 // also a candidate for SSO.
565565 virtual bool IsUndeniableChange( void ) const noexcept = 0;
566566
567+ // Returns true if any denial by an invoked sub-step will also be denied by
568+ // this step after return of the sub-step.
569+ virtual bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept = 0;
570+
567571 // Construction of per-step meta-data.
568572 // By default there is no meta-data.
569573 virtual void GetCalcMetaDataProperties( size_t& size_out, size_t& align_out ) const noexcept
@@ -798,6 +802,11 @@
798802 return true;
799803 }
800804
805+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
806+ {
807+ return true;
808+ }
809+
801810 size_t GetChoiceCount( void ) const noexcept override
802811 {
803812 return 1;
@@ -863,6 +872,11 @@
863872 return true;
864873 }
865874
875+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
876+ {
877+ return true;
878+ }
879+
866880 size_t GetChoiceCount( void ) const noexcept override
867881 {
868882 return 1;
@@ -900,6 +914,11 @@
900914 return true;
901915 }
902916
917+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
918+ {
919+ return true;
920+ }
921+
903922 size_t GetChoiceCount( void ) const noexcept override
904923 {
905924 return 1;
@@ -928,6 +947,11 @@
928947 return true;
929948 }
930949
950+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
951+ {
952+ return true;
953+ }
954+
931955 size_t GetChoiceCount( void ) const noexcept override
932956 {
933957 return 1;
@@ -992,6 +1016,15 @@
9921016 return true;
9931017 }
9941018
1019+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1020+ {
1021+ // If we enter a sub-step then, if that substep itself is not undeniable change aswell,
1022+ // we have to create a copy of the object working-copy. This is because we cannot inherit
1023+ // denial from any sub-step. The case of which the sub-step has no deniability zone
1024+ // is already covered by undeniable-change returning true for it.
1025+ return false;
1026+ }
1027+
9951028 size_t GetChoiceCount( void ) const noexcept override
9961029 {
9971030 // Optimization: we skip the tail node.
@@ -1085,6 +1118,11 @@
10851118 ( this->has_maximum == true && this->max_rep_cnt <= 1 ) );
10861119 }
10871120
1121+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1122+ {
1123+ return ( cur_proc_idx < this->min_rep_cnt || this->has_maximum == true && this->min_rep_cnt > this->max_rep_cnt );
1124+ }
1125+
10881126 size_t GetChoiceCount( void ) const noexcept override
10891127 {
10901128 // Optimization: we skip the tail node.
@@ -1178,6 +1216,11 @@
11781216 return true;
11791217 }
11801218
1219+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1220+ {
1221+ return ( this->alts.GetCount() == 1 );
1222+ }
1223+
11811224 size_t GetChoiceCount( void ) const noexcept override
11821225 {
11831226 return alts.GetCount();
@@ -1342,6 +1385,11 @@
13421385 return ( this->steps.GetCount() <= 1 );
13431386 }
13441387
1388+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1389+ {
1390+ return true;
1391+ }
1392+
13451393 size_t GetChoiceCount( void ) const noexcept override
13461394 {
13471395 return steps.GetCount();
@@ -1464,6 +1512,13 @@
14641512 return ( this->min_item_cnt <= 1 );
14651513 }
14661514
1515+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1516+ {
1517+ size_t cur_item_cnt = ( ( cur_proc_idx + 1 ) / 2 );
1518+
1519+ return ( cur_item_cnt < this->min_item_cnt );
1520+ }
1521+
14671522 size_t GetChoiceCount( void ) const noexcept override
14681523 {
14691524 return 2;
@@ -1615,6 +1670,11 @@
16151670 return true;
16161671 }
16171672
1673+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1674+ {
1675+ return false;
1676+ }
1677+
16181678 inline bool IsStemmingFrom( Step *call ) const
16191679 {
16201680 Step *try_root = this->extended;
@@ -1818,6 +1878,11 @@
18181878 return true;
18191879 }
18201880
1881+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
1882+ {
1883+ return true;
1884+ }
1885+
18211886 size_t GetChoiceCount( void ) const noexcept override
18221887 {
18231888 // We are executing a single step inside.
@@ -1933,6 +1998,11 @@
19331998 return true;
19341999 }
19352000
2001+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
2002+ {
2003+ return ( this->alts.GetCount() == 1 );
2004+ }
2005+
19362006 size_t GetChoiceCount( void ) const noexcept override
19372007 {
19382008 return alts.GetCount();
@@ -2086,6 +2156,11 @@
20862156 return true;
20872157 }
20882158
2159+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
2160+ {
2161+ return true;
2162+ }
2163+
20892164 size_t GetChoiceCount( void ) const noexcept override
20902165 {
20912166 // We can recurse into this node safely with no-progress because we do always
@@ -2210,6 +2285,11 @@
22102285 return true;
22112286 }
22122287
2288+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
2289+ {
2290+ return true;
2291+ }
2292+
22132293 size_t GetChoiceCount( void ) const noexcept override
22142294 {
22152295 // We do know that there would always be just one step at maximum.
@@ -2277,7 +2357,7 @@
22772357
22782358 inline StepReplacementPoint( const StepReplacementPoint& ) = default;
22792359 inline StepReplacementPoint( StepReplacementPoint&& right ) noexcept
2280- : replacements( std::move( right.replacements ) ), valrefs( std::move( right.valrefs ) )
2360+ : Step( std::move( right ) ), replacements( std::move( right.replacements ) ), valrefs( std::move( right.valrefs ) )
22812361 {
22822362 this->exec = right.exec;
22832363
@@ -2396,6 +2476,11 @@
23962476 return true;
23972477 }
23982478
2479+ bool DoesInheritSubStepDenial( size_t cur_proc_idx ) const noexcept override
2480+ {
2481+ return true;
2482+ }
2483+
23992484 size_t GetChoiceCount( void ) const noexcept override
24002485 {
24012486 return 1;
@@ -3322,9 +3407,11 @@
33223407 }
33233408 else if ( prevEntry != nullptr )
33243409 {
3410+ Step *prevStep = prevEntry->current_step;
3411+
33253412 // Just append and take-over to the next entry.
33263413 entry.attrib_prefix = std::move( prevEntry->attrib_prefix );
3327- entry.appendAttributePrefix( prevEntry->current_step->attribute_key.ToFixed() );
3414+ entry.appendAttributePrefix( prevStep->attribute_key.ToFixed() );
33283415 entry.is_attrib_continuation = true;
33293416
33303417 node_selector *sel_man = prevEntry->GetActiveSelector();
@@ -3340,7 +3427,7 @@
33403427 if ( entry.requires_init )
33413428 {
33423429 entry.is_inline_call = true; // We are supposed to take-over this node as replacement on return.
3343- entry.is_sso = current_step->IsUndeniableChange();
3430+ entry.is_sso = ( current_step->IsUndeniableChange() || prevStep->DoesInheritSubStepDenial( prevEntry->process_idx ) );
33443431
33453432 if ( entry.is_sso == false && sel_man != nullptr )
33463433 {
@@ -3422,7 +3509,7 @@
34223509
34233510 if ( has_node || sel_man != nullptr )
34243511 {
3425- // We have SSO exactly if we are undeniable change.
3512+ // We have SSO exactly if we are undeniable change or the previous entry is liable for our denial.
34263513 if ( entry.is_sso )
34273514 {
34283515 if ( has_node )
--- testcompiler/src/cos_tests.cpp (revision 60)
+++ testcompiler/src/cos_tests.cpp (revision 61)
@@ -2070,8 +2070,8 @@
20702070 lexer.GetNamedProduction( "funcsigdecl" ).setSelector <funcsig_selector> ();
20712071 lexer.GetNamedProduction( "funcsigdecl_opt" ).setSelector <funcsig_selector> ();
20722072 }
2073- assert( lexer.CompileProduction( compiler, "locatedname", "name:spec (spaces [arrspec:arrayspec, spaces])" ) == true ); // helper
2074- assert( lexer.CompileProduction( compiler, "locatedname_opt", "(name:spec)^0:1 (spaces [arrspec:arrayspec, spaces])" ) == true ); // helper.
2073+ assert( lexer.CompileProduction( compiler, "locatedname", "name:spec (spaces [arrspec:arrayspec, spaces])^0:1" ) == true ); // helper
2074+ assert( lexer.CompileProduction( compiler, "locatedname_opt", "(name:spec)^0:1 (spaces [arrspec:arrayspec, spaces])^0:1" ) == true ); // helper.
20752075 assert( lexer.CompileProduction( compiler, "arrayspec", "'[' spaces (idx:operation spaces)^0:1 endtok:']'" ) == true ); // helper
20762076 // Set-up both of the following productions in one block.
20772077 assert( lexer.CompileProduction( compiler, "declaration", "utype:spec spaces locator spaces (func:funcsigdecl|locatedname) declinit" ) == true );
@@ -2240,7 +2240,7 @@
22402240
22412241 size_t cstack_cnt = machine.GetCurrentCalcStackSize();
22422242
2243- size_t cstack_idx = ( cstack_cnt - 1 ); // skip us.
2243+ size_t cstack_idx = ( cstack_cnt - 2 ); // skip us.
22442244
22452245 declaration_selector *decl_sel = nullptr;
22462246 multdecl_selector *multdecl_sel = nullptr;
@@ -3605,24 +3605,24 @@
36053605
36063606 assert( root != nullptr );
36073607
3608- SpecifierString *type = dynamic_cast <SpecifierString*> ( root->type );
3608+ PointerTypeSpecifier *type = dynamic_cast <PointerTypeSpecifier*> ( root->type );
36093609
36103610 assert( type != nullptr );
3611- assert( type->string == "mydata" );
36123611
3613- type->Delete();
3612+ SpecifierString *type_spec = dynamic_cast <SpecifierString*> ( type->spec );
36143613
3615- PointerTypeSpecifier *ptrspec = dynamic_cast <PointerTypeSpecifier*> ( root->name );
3614+ assert( type_spec != nullptr );
3615+ assert( type_spec->string == "mydata" );
36163616
3617- assert( ptrspec != nullptr );
3617+ type_spec->Delete();
3618+ type->Delete();
36183619
3619- SpecifierString *name = dynamic_cast <SpecifierString*> ( ptrspec->spec );
3620+ SpecifierString *name = dynamic_cast <SpecifierString*> ( root->name );
36203621
36213622 assert( name != nullptr );
36223623 assert( name->string == "obj" );
36233624
36243625 name->Delete();
3625- ptrspec->Delete();
36263626
36273627 NewOperation *init = dynamic_cast <NewOperation*> ( root->initializer );
36283628
--- testcompiler/src/lexingcomp_tests.cpp (revision 60)
+++ testcompiler/src/lexingcomp_tests.cpp (revision 61)
@@ -607,6 +607,25 @@
607607 }
608608 printf( "ok.\n" );
609609
610+ printf( "testing LexingCompiler replacement-point-step..." );
611+ {
612+ LexingEnvironment <char, LexNodeType> env;
613+ LexingCompiler <char, decltype(env)> compiler;
614+
615+ auto *step = compiler.CompileProduction( &env, "&( \"tuturu\", repl=max )" );
616+
617+ decltype(env)::ProductionMachine machine( &env );
618+
619+ assert( step != nullptr );
620+
621+ machine.Execute( "tuturu", step );
622+
623+ assert( machine.successful == true );
624+
625+ step->Delete();
626+ }
627+ printf( "ok.\n" );
628+
610629 printf( "testing LexingCompiler construction with object allocator..." );
611630 {
612631 LexingEnvironment <char, LexNodeType, EirHeapLinkAllocator> env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
--- testcompiler/src/lexingenv_tests.cpp (revision 60)
+++ testcompiler/src/lexingenv_tests.cpp (revision 61)
@@ -683,6 +683,61 @@
683683 }
684684 printf( "ok.\n" );
685685
686+ printf( "testing ProductionMachine denial-inheritance-guarantee optimization..." );
687+ {
688+ // It should be a natural idea that enclosing inline sequences should contribute to the
689+ // same working-copy object like the sequence which encloses them, especially if they are
690+ // direct children of it. So we test this basic idea that is made possible due to the
691+ // latest optimization.
692+
693+ static bool has_been_cloned = false;
694+
695+ struct BasicObject : public LexNodeType
696+ {
697+ using LexNodeType::LexNodeType;
698+
699+ LexNodeType* Clone( void ) override
700+ {
701+ has_been_cloned = true;
702+
703+ return new BasicObject();
704+ }
705+
706+ void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value ) override
707+ {
708+ return;
709+ }
710+ };
711+
712+ TestAllocEnv env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
713+
714+ decltype(env)::StepToken testtok( &env );
715+ testtok.token_str = "T";
716+ testtok.attribute_key = "attr";
717+
718+ decltype(env)::SerializedStep subseq( &env );
719+ subseq.SetConnections( { &testtok, &testtok, &testtok } );
720+
721+ decltype(env)::SerializedStep mainseq( &env );
722+ mainseq.SetConnections( { &testtok, &subseq, &testtok } );
723+ mainseq.setConstructor(
724+ []
725+ {
726+ return new BasicObject();
727+ }
728+ );
729+
730+ decltype(env)::ProductionMachine machine( &env );
731+
732+ machine.Execute( "TTTTT", &mainseq );
733+
734+ assert( machine.successful == true );
735+
736+ // This will fail if the optimization is not present.
737+ assert( has_been_cloned == false );
738+ }
739+ printf( "ok.\n" );
740+
686741 printf( "testing ProductionMachine StepExtend..." );
687742 {
688743 TestAllocEnv env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
Show on old repository browser