• R/O
  • SSH
  • HTTPS

eircompile: Commit


Commit MetaInfo

Revision58 (tree)
Time2021-11-30 00:15:54
Authorquiret

Log Message

- actually implemented the step-extension reordering logic
- added StepCustomIndirection, a callback-based lexer production type that can select the next step based on calculation-path properties such as previously built nodes + made unit tests for it

Change Summary

Incremental Difference

--- eircompile/include/eircompile/lexing_compile.h (revision 57)
+++ eircompile/include/eircompile/lexing_compile.h (revision 58)
@@ -101,13 +101,16 @@
101101
102102 typename cenv_t::SerializedStep spaced_comma_tok = &cenv;
103103
104+ typename cenv_t::StepToken tok_attributes_begin = &cenv;
105+ typename cenv_t::StepToken tok_attributes_end = &cenv;
106+
104107 typename cenv_t::StepToken sepstep_tok_allow_item_term = &cenv;
105108 typename cenv_t::StepToken comma_tok = &cenv;
106109 typename cenv_t::SerializedStep sepstep_allow_item_term = &cenv;
107110 typename cenv_t::StepRepeatByInterval sepstep_opt_allow_item_term = &cenv;
108111 typename cenv_t::StepAttribution sepstep_attrib_mincnt = &cenv;
109- typename cenv_t::StepToken sepstep_tok_attributes_begin = &cenv;
110- typename cenv_t::StepToken sepstep_tok_attributes_end = &cenv;
112+ // sepstep_tok_attributes_begin = tok_attributes_begin
113+ // sepstep_tok_attributes_end = tok_attributes_end
111114 typename cenv_t::SerializedStep sepstep_attributes = &cenv;
112115 typename cenv_t::StepRepeatByInterval sepstep_opt_attributes = &cenv;
113116 typename cenv_t::StepToken sepstep_tok_begin = &cenv;
@@ -123,6 +126,9 @@
123126 typename cenv_t::StepAlternatives extstep_attrib = &cenv;
124127 typename cenv_t::SerializedStep extstep_attrib_spacesappend = &cenv;
125128 typename cenv_t::StepRepeatByInterval extstep_opt_attrib = &cenv;
129+ typename cenv_t::StepToken extstep_tok_before_usual = &cenv;
130+ typename cenv_t::SerializedStep extstep_seq_itemattrib = &cenv;
131+ typename cenv_t::StepRepeatByInterval extstep_opt_seq_itemattrib = &cenv;
126132 typename cenv_t::SerializedStep seqextend_prodseq = &cenv;
127133 typename cenv_t::SerializedStep seqextend = &cenv;
128134
@@ -536,6 +542,9 @@
536542 // We now get to the steps which are either procgated or have enclosings/prefixes.
537543 producible.AddConnection( &safe_enclosed_prod );
538544
545+ tok_attributes_begin.token_str = _Token_LessThan <charType> ();
546+ tok_attributes_end.token_str = _Token_GreaterThan <charType> ();
547+
539548 // *** SEPARATIONS ***
540549
541550 // [<min,e>item,sep], [<min>item,sep], [item,sep]
@@ -556,16 +565,13 @@
556565 sepstep_attrib_mincnt.SetNode( &numeric );
557566 sepstep_attrib_mincnt.attribute_key = _AttribKey_MinToken <charType> ();
558567
559- sepstep_tok_attributes_begin.token_str = _Token_LessThan <charType> ();
560- sepstep_tok_attributes_end.token_str = _Token_GreaterThan <charType> ();
561-
562568 sepstep_attributes.SetConnections( {
563- &sepstep_tok_attributes_begin,
569+ &tok_attributes_begin,
564570 &spaces,
565571 &sepstep_attrib_mincnt,
566572 &sepstep_opt_allow_item_term,
567573 &spaces,
568- &sepstep_tok_attributes_end
574+ &tok_attributes_end
569575 } );
570576
571577 sepstep_opt_attributes.SetNode( &sepstep_attributes );
@@ -624,7 +630,7 @@
624630
625631 // *** EXTEND STEP ***
626632
627- // ^( ("extended")^0:1 extended, extension )
633+ // ^( ("extended")^0:1 extended, ("<b>")^0:1 extension )
628634 tok_extend_beg.token_str = _Token_Elevation <charType> ();
629635 tok_extend_beg.token_str += _Token_CurlyBrackets_Begin <charType> ();
630636
@@ -638,6 +644,21 @@
638644 extstep_opt_attrib.max_rep_cnt = 1;
639645 extstep_opt_attrib.attribute_key = _AttribKey_Attribute <charType> ();
640646
647+ extstep_tok_before_usual.token_str = _Token_ExtensionProcessBefore <charType> ();
648+ extstep_tok_before_usual.attribute_key = _AttribKey_ExtensionAttrib <charType> ();
649+
650+ extstep_seq_itemattrib.SetConnections( {
651+ &tok_attributes_begin,
652+ &extstep_tok_before_usual,
653+ &tok_attributes_end,
654+ &spaces
655+ } );
656+
657+ extstep_opt_seq_itemattrib.SetNode( &extstep_seq_itemattrib );
658+ extstep_opt_seq_itemattrib.min_rep_cnt = 0;
659+ extstep_opt_seq_itemattrib.has_maximum = true;
660+ extstep_opt_seq_itemattrib.max_rep_cnt = 1;
661+
641662 seqextend_prodseq.SetConnections( {
642663 &extstep_opt_attrib,
643664 &spaces,
@@ -649,6 +670,7 @@
649670 &spaces,
650671 &seqextend_prodseq,
651672 &spaced_comma_tok,
673+ &extstep_opt_seq_itemattrib,
652674 &producible_procgate,
653675 &spaces,
654676 &tok_cbrackets_end
@@ -670,7 +692,7 @@
670692
671693 // *** EXTENSION-POINT STEP ***
672694
673- // ^!(p, extend1+extension1, extend2+extension2, ..., extendn+extensionn)
695+ // ^!(p, ("<b>")^0:1 extend1+extension1, ("<b>")^0:1 extend2+extension2, ..., ("<b>")^0:1 extendn+extensionn)
674696 tok_extpt_begin.token_str = _Token_Elevation <charType> ();
675697 tok_extpt_begin.token_str += _Token_ExclamationPoint <charType> ();
676698 tok_extpt_begin.token_str += _Token_CurlyBrackets_Begin <charType> ();
@@ -678,6 +700,7 @@
678700 tok_plus.token_str = _Token_Plus <charType> ();
679701
680702 seqextpt_extitem.SetConnections( {
703+ &extstep_opt_seq_itemattrib,
681704 &seqextend_prodseq,
682705 &spaces,
683706 &tok_plus,
@@ -1107,7 +1130,7 @@
11071130 template <eir::CharacterType charType>
11081131 static AINLINE bool IsAttribCharacter( charType ucp )
11091132 {
1110- static const char validchars[] = "abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
1133+ static const char validchars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-";
11111134
11121135 for ( char c : validchars )
11131136 {
@@ -1303,6 +1326,31 @@
13031326 }
13041327
13051328 template <eir::CharacterType charType>
1329+ static AINLINE const charType* _AttribKey_ExtensionAttrib( void ) noexcept
1330+ {
1331+ if constexpr ( std::same_as <charType, char> )
1332+ {
1333+ return "extattrib";
1334+ }
1335+ if constexpr ( std::same_as <charType, wchar_t> )
1336+ {
1337+ return L"extattrib";
1338+ }
1339+ if constexpr ( std::same_as <charType, char8_t> )
1340+ {
1341+ return u8"extattrib";
1342+ }
1343+ if constexpr ( std::same_as <charType, char16_t> )
1344+ {
1345+ return u"extattrib";
1346+ }
1347+ if constexpr ( std::same_as <charType, char32_t> )
1348+ {
1349+ return U"extattrib";
1350+ }
1351+ }
1352+
1353+ template <eir::CharacterType charType>
13061354 static AINLINE const charType* _AttribKey_ProductionNode( void ) noexcept
13071355 {
13081356 if constexpr ( std::same_as <charType, char> )
@@ -1777,6 +1825,31 @@
17771825 }
17781826
17791827 template <eir::CharacterType charType>
1828+ static AINLINE const charType* _Token_ExtensionProcessBefore( void ) noexcept
1829+ {
1830+ if constexpr ( std::same_as <charType, char> )
1831+ {
1832+ return "b";
1833+ }
1834+ if constexpr ( std::same_as <charType, wchar_t> )
1835+ {
1836+ return L"b";
1837+ }
1838+ if constexpr ( std::same_as <charType, char8_t> )
1839+ {
1840+ return u8"b";
1841+ }
1842+ if constexpr ( std::same_as <charType, char16_t> )
1843+ {
1844+ return u"b";
1845+ }
1846+ if constexpr ( std::same_as <charType, char32_t> )
1847+ {
1848+ return U"b";
1849+ }
1850+ }
1851+
1852+ template <eir::CharacterType charType>
17801853 static AINLINE const charType* _Token_LessThan( void ) noexcept
17811854 {
17821855 if constexpr ( std::same_as <charType, char> )
@@ -1917,6 +1990,13 @@
19171990 {
19181991 this->SetExtendedNode( &this->env->nonterminal_namespace.get( value, this->env ) );
19191992 }
1993+ else if ( attrib == _AttribKey_ExtensionAttrib <charType> () )
1994+ {
1995+ if ( value == _Token_ExtensionProcessBefore <charType> () )
1996+ {
1997+ this->extension_is_before_usual = true;
1998+ }
1999+ }
19202000 }
19212001
19222002 bool AssignNode( const eir::FixedString <charType>& attrib, ExecStep *node ) override
--- eircompile/include/eircompile/lexing_env.h (revision 57)
+++ eircompile/include/eircompile/lexing_env.h (revision 58)
@@ -1507,10 +1507,12 @@
15071507 this->extended = right.extended;
15081508 this->extension = right.extension;
15091509 this->extended_base_on_extension = right.extended_base_on_extension;
1510+ this->extension_is_before_usual = right.extension_is_before_usual;
15101511
15111512 right.extended = nullptr;
15121513 right.extension = nullptr;
15131514 right.extended_base_on_extension = false;
1515+ right.extension_is_before_usual = false;
15141516 }
15151517 inline StepExtend( const StepExtend& right ) = default;
15161518
@@ -1587,8 +1589,9 @@
15871589 bool extended_base_on_extension = false; // if true then we look for a most-recent extension of the step to base ourselves on, if failure then the step directly.
15881590 private:
15891591 Step *extension = nullptr;
1592+ public:
1593+ bool extension_is_before_usual = false; // if true then the extension steps are executed before the extended steps; by default extensions are executed afterward.
15901594
1591- public:
15921595 void SetExtendedNode( Step *node )
15931596 {
15941597 Step *extended = this->extended;
@@ -2101,6 +2104,110 @@
21012104 }
21022105 };
21032106
2107+ // Forward declaration.
2108+ struct ProductionMachine;
2109+
2110+ struct StepCustomIndirection : public Step
2111+ {
2112+ friend struct LexingEnvironment;
2113+
2114+ using Step::Step;
2115+
2116+ inline StepCustomIndirection( const StepCustomIndirection& ) = default;
2117+ inline StepCustomIndirection( StepCustomIndirection&& ) = default;
2118+
2119+ inline ~StepCustomIndirection( void )
2120+ {
2121+ auto *env = this->env;
2122+
2123+ for ( Step *n : refs )
2124+ {
2125+ env->gcReachSched.OnRemoveConnection( this, n );
2126+ }
2127+ }
2128+
2129+ Step* Clone( void ) override
2130+ {
2131+ return this->env->CloneStep <StepCustomIndirection> ( this );
2132+ }
2133+
2134+ Step* GetNextConnectionsToNode( Step *prev ) override
2135+ {
2136+ auto *nextNode = this->refs.FindJustAbove( prev );
2137+
2138+ return ( nextNode ? nextNode->GetValue() : nullptr );
2139+ }
2140+
2141+ bool IsUnambiguousCall( void ) const noexcept override
2142+ {
2143+ // Just like call or attribution, this Step does pick a next one.
2144+ return true;
2145+ }
2146+
2147+ bool IsUndeniableChange( void ) const noexcept override
2148+ {
2149+ // This step itself does not change a thing but the below one which gets picked next would
2150+ // be re-evaluated based on it's own metrics so we are safe to return true regardless.
2151+ return true;
2152+ }
2153+
2154+ size_t GetChoiceCount( void ) const noexcept override
2155+ {
2156+ // We do know that there would always be just one step at maximum.
2157+ // It is not valid to return different steps for the same calculation path conditions.
2158+ return 1;
2159+ }
2160+
2161+ private:
2162+ DEFINE_HEAP_REDIR_ALLOC_BYSTRUCT( refs_redirAlloc, allocatorType );
2163+
2164+ eir::Set <Step*, refs_redirAlloc> refs;
2165+
2166+ DEFINE_HEAP_REDIR_ALLOC_BYSTRUCT( callback_redirAlloc, allocatorType );
2167+
2168+ public:
2169+ eir::Function <callback_redirAlloc, eir::DefaultExceptionManager, Step*, ProductionMachine& /* machine */> callback;
2170+
2171+ // Sets the use-connections for the garbage collectors.
2172+ // This way the sub-steps are kept alive for at-least as long as this step is.
2173+ inline void SetConnections( const depVector <Step*> refs )
2174+ {
2175+ LexingEnvironment *env = this->env;
2176+
2177+ for ( Step *n : refs )
2178+ {
2179+ if ( this->refs.Find( n ) == nullptr )
2180+ {
2181+ this->refs.Insert( n );
2182+
2183+ env->gcReachSched.OnAddedConnection( this, n );
2184+ }
2185+ }
2186+ }
2187+
2188+ inline void AddConnection( Step *n )
2189+ {
2190+ if ( this->refs.Find( n ) )
2191+ return;
2192+
2193+ this->refs.Insert( n );
2194+
2195+ this->env->gcReachSched.OnAddedConnection( this, n );
2196+ }
2197+
2198+ inline void RemoveConnection( Step *n )
2199+ {
2200+ auto *findNode = this->refs.Find( n );
2201+
2202+ if ( findNode == nullptr )
2203+ return;
2204+
2205+ this->refs.RemoveNode( findNode );
2206+
2207+ this->env->gcReachSched.OnRemoveConnection( this, n );
2208+ }
2209+ };
2210+
21042211 struct EnvironmentAllocator
21052212 {
21062213 inline EnvironmentAllocator( LexingEnvironment *env ) noexcept : env( env )
@@ -2489,9 +2596,13 @@
24892596 this->debug_breaks = std::move( right.debug_breaks );
24902597 this->resultNode = right.resultNode;
24912598 this->successful = right.successful;
2599+ this->current_calc_stack = right.current_calc_stack;
2600+ this->current_calc_stack_top = right.current_calc_stack_top;
24922601
24932602 right.resultNode = nullptr;
24942603 right.successful = false;
2604+ right.current_calc_stack = nullptr;
2605+ right.current_calc_stack_top = nullptr;
24952606 }
24962607 inline ProductionMachine( const ProductionMachine& ) = delete;
24972608
@@ -2516,6 +2627,16 @@
25162627 eir::Vector <CalcPathEntry, EnvironmentAllocator> _calc_stack( eir::constr_with_alloc::DEFAULT, this->env );
25172628 CalcPathEntry entry( start_step ); // top of the calc_stack, on the C++-stack for better performance.
25182629
2630+ // We mandate that there can be only one concurrent execution task at a time.
2631+ this->current_calc_stack = &_calc_stack;
2632+ this->current_calc_stack_top = &entry;
2633+
2634+ auto cleanup_calc_links = [&]( void )
2635+ {
2636+ this->current_calc_stack = nullptr;
2637+ this->current_calc_stack_top = nullptr;
2638+ };
2639+
25192640 auto get_calcstack_size = [&]( void ) -> size_t
25202641 {
25212642 return ( _calc_stack.GetCount() + 1 );
@@ -3434,7 +3555,9 @@
34343555 }
34353556 else
34363557 {
3437- if ( idx == 0 )
3558+ bool extension_is_before_usual = extstep->extension_is_before_usual;
3559+
3560+ if ( extension_is_before_usual == false && idx == 0 || extension_is_before_usual == true && idx == 1 )
34383561 {
34393562 size_t calcstack_size = get_calcstack_size();
34403563
@@ -3457,7 +3580,7 @@
34573580 // Extension-search should know that the frame is not the most-special one.
34583581 entry.was_called_by_extend = true;
34593582 }
3460- else
3583+ else if ( extension_is_before_usual == false && idx == 1 || extension_is_before_usual == true && idx == 0 )
34613584 {
34623585 Step *next_step = extstep->extension;
34633586
@@ -3531,6 +3654,16 @@
35313654 }
35323655 }
35333656 }
3657+ else if ( StepCustomIndirection *indirstep = dynamic_cast <StepCustomIndirection*> ( current_step ) )
3658+ {
3659+ Step *next_step = indirstep->callback( *this );
3660+
3661+ if ( next_step == nullptr || push_onto_execution( next_step ) == false )
3662+ {
3663+ has_op_finished = true;
3664+ is_op_successful = false;
3665+ }
3666+ }
35343667 else
35353668 {
35363669 FATAL_ABORT();
@@ -3849,6 +3982,7 @@
38493982
38503983 if ( has_node || has_selector )
38513984 {
3985+ entry.appendAttributePrefix( current_step->attribute_key.ToFixed() );
38523986 entry.appendAttributePrefix( prev_step->attribute_key.ToFixed() );
38533987 try
38543988 {
@@ -3888,6 +4022,7 @@
38884022 is_op_successful = false;
38894023 }
38904024 entry.debuildAttributePrefix( prev_step->attribute_key.ToFixed() );
4025+ entry.debuildAttributePrefix( current_step->attribute_key.ToFixed() );
38914026 }
38924027 // If we are successful and there is no node in the previous step and the previous
38934028 // step is not ambiguous, then write the node as result.
@@ -4025,6 +4160,7 @@
40254160 // StepCall
40264161 // StepAttribution
40274162 // StepProceduralSequence
4163+ // StepCustomIndirection
40284164
40294165 // This opcode has no further special handling.
40304166 has_op_finished = true;
@@ -4060,8 +4196,12 @@
40604196 leave_execution( entry );
40614197 }
40624198
4199+ cleanup_calc_links();
4200+
40634201 throw;
40644202 }
4203+
4204+ cleanup_calc_links();
40654205 }
40664206
40674207 inline cNodeType* DetachNode( void ) noexcept
@@ -4099,10 +4239,119 @@
40994239 }
41004240 }
41014241
4242+ // *** BEGIN METHODS FOR STEPS WITH CUSTOM CALLBACKS ***
4243+
4244+ inline size_t GetCurrentCalcStackSize( void ) const noexcept
4245+ {
4246+ size_t calc_stack_size = 0;
4247+
4248+ if ( this->current_calc_stack_top )
4249+ {
4250+ calc_stack_size++;
4251+ }
4252+
4253+ if ( auto *current_calc_stack = this->current_calc_stack )
4254+ {
4255+ calc_stack_size += current_calc_stack->GetCount();
4256+ }
4257+
4258+ return calc_stack_size;
4259+ }
4260+
4261+ inline size_t GetCurrentCalcStackMostRecentIndex( Step *node ) const
4262+ {
4263+ auto *current_calc_stack = this->current_calc_stack;
4264+ CalcPathEntry *current_calc_stack_top = this->current_calc_stack_top;
4265+
4266+ if ( current_calc_stack == nullptr || current_calc_stack_top == nullptr )
4267+ {
4268+ throw eir::eir_exception();
4269+ }
4270+
4271+ size_t _calc_stack_size_notop = ( current_calc_stack->GetCount() );
4272+
4273+ if ( node == current_calc_stack_top->current_step )
4274+ {
4275+ return _calc_stack_size_notop;
4276+ }
4277+
4278+ while ( _calc_stack_size_notop > 0 )
4279+ {
4280+ _calc_stack_size_notop--;
4281+
4282+ CalcPathEntry& cur_ent = (*current_calc_stack)[ _calc_stack_size_notop ];
4283+
4284+ if ( cur_ent.current_step == node )
4285+ {
4286+ return _calc_stack_size_notop;
4287+ }
4288+ }
4289+
4290+ throw eir::eir_exception();
4291+ }
4292+
4293+ private:
4294+ AINLINE CalcPathEntry& GetCurrentExecutionCalcPathEntryByIndex( size_t cstack_idx ) const
4295+ {
4296+ auto *current_calc_stack = this->current_calc_stack;
4297+ CalcPathEntry *current_calc_stack_top = this->current_calc_stack_top;
4298+
4299+ if ( current_calc_stack == nullptr || current_calc_stack_top == nullptr )
4300+ {
4301+ throw eir::eir_exception();
4302+ }
4303+
4304+ size_t _cstack_size_notop = current_calc_stack->GetCount();
4305+ size_t cstack_size = ( 1 + _cstack_size_notop );
4306+
4307+ if ( cstack_idx >= cstack_size )
4308+ {
4309+ throw eir::eir_exception();
4310+ }
4311+
4312+ if ( cstack_idx == _cstack_size_notop )
4313+ {
4314+ return *current_calc_stack_top;
4315+ }
4316+
4317+ CalcPathEntry& ent = (*current_calc_stack)[ cstack_idx ];
4318+
4319+ return ent;
4320+ }
4321+
4322+ public:
4323+ inline Step* GetCurrentExecutionStepByIndex( size_t cstack_idx ) const
4324+ {
4325+ CalcPathEntry& ent = GetCurrentExecutionCalcPathEntryByIndex( cstack_idx );
4326+
4327+ return ent.current_step;
4328+ }
4329+
4330+ inline cNodeType* GetCurrentExecutionNodeByIndex( size_t cstack_idx ) const
4331+ {
4332+ CalcPathEntry& ent = GetCurrentExecutionCalcPathEntryByIndex( cstack_idx );
4333+
4334+ return std::get <cNodeType*> ( ent.pcalc );
4335+ }
4336+
4337+ // Returns the selector-meta-data that is provided for construction by the setSelector template parameter.
4338+ // Using this method does require knowledge about the production hierarchy and their node construction behaviour.
4339+ inline void* GetCurrentExecutionSelectorDataByIndex( size_t cstack_idx ) const
4340+ {
4341+ CalcPathEntry& ent = GetCurrentExecutionCalcPathEntryByIndex( cstack_idx );
4342+
4343+ return ent.selectorMetaData;
4344+ }
4345+
4346+ // *** END METHODS FOR STEPS WITH CUSTOM CALLBACKS ***
4347+
41024348 LexingEnvironment *env;
41034349 bool successful = false;
41044350 cNodeType *resultNode = nullptr;
41054351
4352+ eir::Vector <CalcPathEntry, EnvironmentAllocator> *current_calc_stack = nullptr;
4353+ CalcPathEntry *current_calc_stack_top = nullptr;
4354+
41064355 private:
41074356 DEFINE_HEAP_REDIR_ALLOC_BYSTRUCT( debug_breaks_redirAlloc, allocatorType );
41084357
@@ -4150,6 +4399,8 @@
41504399 IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, StepExtensionPoint::extensions_redirAlloc, StepExtensionPoint, extensions, env->allocMan, allocatorType );
41514400 IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, StepProceduralAlternatives::alts_redirAlloc, StepProceduralAlternatives, alts, env->allocMan, allocatorType );
41524401 IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, StepProceduralSequence::steps_redirAlloc, StepProceduralSequence, steps, env->allocMan, allocatorType );
4402+IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, StepCustomIndirection::refs_redirAlloc, StepCustomIndirection, refs, env->allocMan, allocatorType );
4403+IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, StepCustomIndirection::callback_redirAlloc, StepCustomIndirection, callback, env->allocMan, allocatorType );
41534404 IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, ProductionMachine::CalcPathEntry::attrib_prefix_redirAlloc, CalcPathEntry, attrib_prefix, current_step->env->allocMan, allocatorType );
41544405 IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, ProductionMachine::CalcPathEntry::noprogress_map_redirAlloc, CalcPathEntry, noprogress_map, current_step->env->allocMan, allocatorType );
41554406 IMPL_HEAP_REDIR_DYN_ALLOC_TEMPLATEBASE( LexingEnvironment, LEXENV_TEMPLARGS_NODEF, LEXENV_TEMPLUSE, ProductionMachine::debug_breaks_redirAlloc, ProductionMachine, debug_breaks, env->allocMan, allocatorType );
--- testcompiler/src/cos_tests.cpp (revision 57)
+++ testcompiler/src/cos_tests.cpp (revision 58)
@@ -674,8 +674,8 @@
674674 };
675675 lexer.GetNamedProduction( "S" ).setSelector <mintwo_specialized_selector <char, Program, COSNode, program_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
676676 }
677- assert( lexer.CompileProduction( compiler, "statement", "function | typedef | block | loop | if | except | objmod | takefirst declaration spaces ';' | takefirst operation spaces ';'" ) == true );
678- assert( lexer.CompileProduction( compiler, "function", "(type:spec spaces)^0:1 (\"func\" | \"operator\") spaces name:spec spaces '(' spaces param:paramlist spaces ')' spaces body:funcbody" ) == true );
677+ assert( lexer.CompileProduction( compiler, "statement", "function | typedef | block | loop | if | except | objmod | takefirst multdecl spaces ';' | takefirst operation spaces ';'" ) == true );
678+ assert( lexer.CompileProduction( compiler, "function", "(type:spec spaces)^0:1 (\"func\" | \"operator\") spaces name:spec spaces '(' spaces paramlist spaces ')' spaces body:funcbody" ) == true );
679679 {
680680 struct function_dispatcher
681681 {
@@ -706,7 +706,7 @@
706706 };
707707 lexer.GetNamedProduction( "function" ).setSelector <direct_obj_build_selector <char, FunctionDefinition, COSNode, function_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
708708 }
709- assert( lexer.CompileProduction( compiler, "paramlist", "[<0>declaration, spaces ',' spaces]" ) == true );
709+ assert( lexer.CompileProduction( compiler, "paramlist", "[<0>param:declaration, spaces ',' spaces]" ) == true );
710710 assert( lexer.CompileProduction( compiler, "funcbody", "^!(block, <b> statement+funcstatement)" ) == true );
711711 assert( lexer.CompileProduction( compiler, "funcstatement", "\"return\" spaces (op:operation spaces)^0:1 ';'" ) == true );
712712 {
@@ -757,32 +757,6 @@
757757 };
758758 lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, PointerTypeSpecifier, COSNode, ptr_spec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
759759 }
760- assert( lexer.CompileProduction( compiler, "declaration", "(type:spec spaces)^0:1 name:spec ( spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true );
761- {
762- struct declaration_dispatcher
763- {
764- static inline bool AssignNodeTo( DeclarationStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
765- {
766- if ( attrib == "type" )
767- {
768- assign_to->type = node;
769- return true;
770- }
771- else if ( attrib == "name" )
772- {
773- assign_to->name = node;
774- return true;
775- }
776- else if ( attrib == "init" )
777- {
778- assign_to->initializer = node;
779- return true;
780- }
781- return false;
782- }
783- };
784- lexer.GetNamedProduction( "declaration" ).setSelector <direct_obj_build_selector <char, DeclarationStatement, COSNode, declaration_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
785- }
786760 assert( lexer.CompileProduction( compiler, "dtypedef", "\"typedef\" spaces srctype:spec spaces dsttype:spec spaces ';'" ) == true );
787761 {
788762 struct typedef_dispatcher
@@ -1385,7 +1359,7 @@
13851359
13861360 auto tailop = lexer.MakeStep <decltype(lexer)::RuntimeEnv::StepAlternatives> ();
13871361
1388- assert( lexer.CompileInto( compiler, tailop, "\"new\" spaces type:spec spaces ('(' spaces param:paramlist spaces ')')^0:1" ) == true );
1362+ assert( lexer.CompileInto( compiler, tailop, "\"new\" spaces type:spec spaces ('(' spaces paramlist spaces ')')^0:1" ) == true );
13891363 {
13901364 struct new_dispatcher
13911365 {
@@ -1741,7 +1715,7 @@
17411715 }
17421716 assert( lexer.CompileProduction( compiler, "typedef", "dtypedef | structdef" ) == true );
17431717 assert( lexer.CompileProduction( compiler, "typestatement", "constructor | destructor" ) == true );
1744- assert( lexer.CompileProduction( compiler, "constructor", "\"constructor\" spaces '(' spaces param:paramlist spaces ')' spaces body:extended funcbody" ) == true );
1718+ assert( lexer.CompileProduction( compiler, "constructor", "\"constructor\" spaces '(' spaces paramlist spaces ')' spaces body:extended funcbody" ) == true );
17451719 {
17461720 struct constructor_dispatcher
17471721 {
@@ -1848,7 +1822,58 @@
18481822 };
18491823 lexer.GetNamedProduction( "curlypack" ).setSelector <direct_obj_build_selector <char, CurlyPack, COSNode, curlypack_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
18501824 }
1825+
1826+ // Type system COS structures.
1827+ assert( lexer.CompileProduction( compiler, "declinit", "( spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true );
1828+ assert( lexer.CompileProduction( compiler, "locator", "loc:'*' spaces locator | loc:'&' | loc:'*'" ) == true );
1829+ assert( lexer.CompileProduction( compiler, "multdecl", "(utype:spec spaces)^0:1 [locatedname declinit, spaces ',' spaces]" ) == true );
1830+ {
1831+ struct declaratory_type_builder
1832+ {
18511833
1834+ };
1835+
1836+ struct multdecl_simple_selector
1837+ {
1838+
1839+ COSNode *type;
1840+ };
1841+ }
1842+ assert( lexer.CompileProduction( compiler, "multdecl", "[funcsigdecl declinit, spaces ',' spaces]" ) == true );
1843+ assert( lexer.CompileProduction( compiler, "funcsigdecl", "rtype:type spaces (\"func\" | \"proto\") spaces '(' spaces locatedname spaces ')' spaces '(' spaces paramlist spaces ')'" ) == true );
1844+ assert( lexer.CompileProduction( compiler, "locatedname", "(locator spaces)^0:1 name:spec (spaces [arrspec:arrayspec, spaces])" ) == true );
1845+ assert( lexer.CompileProduction( compiler, "arrayspec", "'[' spaces (idx:operation spaces)^0:1 ']'" ) == true );
1846+ assert( lexer.CompileProduction( compiler, "declaration", "(type:spec spaces)^0:1 locatedname declinit" ) == true );
1847+ {
1848+ // TODO: adjust this to match the lexing capabilities.
1849+ struct declaration_dispatcher
1850+ {
1851+ static inline bool AssignNodeTo( DeclarationStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
1852+ {
1853+ if ( attrib == "type" )
1854+ {
1855+ assign_to->type = node;
1856+ return true;
1857+ }
1858+ else if ( attrib == "name" )
1859+ {
1860+ assign_to->name = node;
1861+ return true;
1862+ }
1863+ else if ( attrib == "init" )
1864+ {
1865+ assign_to->initializer = node;
1866+ return true;
1867+ }
1868+ return false;
1869+ }
1870+ };
1871+ lexer.GetNamedProduction( "declaration" ).setSelector <direct_obj_build_selector <char, DeclarationStatement, COSNode, declaration_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
1872+ }
1873+ assert( lexer.CompileProduction( compiler, "declaration", "funcsigdecl declinit" ) == true );
1874+ assert( lexer.CompileProduction( compiler, "type", "utype:spec (spaces locator)^0:1 (spaces [arrspec:arrayspec, spaces])" ) == true );
1875+ assert( lexer.CompileProduction( compiler, "type", "rtype:type spaces (\"func\" | \"proto\") spaces '(' spaces (locator spaces)^0:1 ([arrspec:arrayspec, spaces] spaces)^0:1 ')' spaces '(' spaces paramlist spaces ')'" ) == true );
1876+
18521877 printf( "testing COS operations (non-deep)..." );
18531878 {
18541879 assert( lexer.TestProduction( "1 + 1;" ) == true );
--- testcompiler/src/lexingenv_tests.cpp (revision 57)
+++ testcompiler/src/lexingenv_tests.cpp (revision 58)
@@ -5615,6 +5615,558 @@
56155615 }
56165616 printf( "ok.\n" );
56175617
5618+ printf( "testing ProductionMachine StepCustomIndirection..." );
5619+ {
5620+ // We perform a declaration-building test, which is what we would do in COS anyway but more complex.
5621+
5622+ static size_t _alive_node_count = 0;
5623+
5624+ struct node
5625+ {
5626+ inline node( void ) noexcept
5627+ {
5628+ _alive_node_count++;
5629+ }
5630+ inline node( const node& right )
5631+ {
5632+ _alive_node_count++;
5633+ }
5634+ inline node( node&& right ) noexcept
5635+ {
5636+ _alive_node_count++;
5637+ }
5638+
5639+ virtual ~node( void )
5640+ {
5641+ _alive_node_count--;
5642+ }
5643+
5644+ inline void Delete( void ) noexcept
5645+ {
5646+ delete this;
5647+ }
5648+ };
5649+
5650+ struct spec : public node
5651+ {
5652+ inline spec( depString <char> token = {} ) noexcept : token( std::move( token ) )
5653+ {}
5654+
5655+ depString <char> token;
5656+ };
5657+
5658+ struct unary : public node
5659+ {
5660+ inline unary( node *sub ) noexcept : sub( sub )
5661+ {}
5662+
5663+ node *sub;
5664+ };
5665+
5666+ struct ptrloc : public unary
5667+ {
5668+ using unary::unary;
5669+ };
5670+ struct refloc : public unary
5671+ {
5672+ using unary::unary;
5673+ };
5674+
5675+ struct arrspec : public unary
5676+ {
5677+ using unary::unary;
5678+ };
5679+
5680+ struct decl : public node
5681+ {
5682+ inline decl( node *type = nullptr, node *name = nullptr, node *init = nullptr ) noexcept : type( type ), name( name ), init( init )
5683+ {
5684+ return;
5685+ }
5686+
5687+ node *type = nullptr;
5688+ node *name = nullptr;
5689+ node *init = nullptr;
5690+ };
5691+
5692+ struct arrnode : public node
5693+ {
5694+ depVector <node*> items;
5695+ };
5696+
5697+ LexingEnvironment <char, node, EirHeapLinkAllocator> env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
5698+
5699+ decltype(env)::StepToken tok_arrspec( &env );
5700+ tok_arrspec.token_str = "[]";
5701+
5702+ decltype(env)::StepToken tok_ptr( &env );
5703+ tok_ptr.token_str = "*";
5704+
5705+ decltype(env)::StepToken tok_ref( &env );
5706+ tok_ref.token_str = "&";
5707+
5708+ decltype(env)::StepRepeatAny repptr( &env );
5709+ repptr.SetNode( &tok_ptr );
5710+ repptr.attribute_key = "loc";
5711+
5712+ decltype(env)::StepRepeatByInterval opt_ref( &env );
5713+ opt_ref.SetNode( &tok_ref );
5714+ opt_ref.min_rep_cnt = 0;
5715+ opt_ref.has_maximum = true;
5716+ opt_ref.max_rep_cnt = 1;
5717+ opt_ref.attribute_key = "loc";
5718+
5719+ decltype(env)::StepToken tok_whitespace( &env );
5720+ tok_whitespace.token_str = " ";
5721+
5722+ decltype(env)::StepRepeatAny spaces( &env );
5723+ spaces.SetNode( &tok_whitespace );
5724+
5725+ decltype(env)::SerializedStep locator( &env );
5726+ locator.SetConnections( { &repptr, &opt_ref, &spaces } );
5727+
5728+ decltype(env)::StepRepeatAny reparrspec( &env );
5729+ reparrspec.SetNode( &tok_arrspec );
5730+ reparrspec.attribute_key = "arrspec";
5731+
5732+ decltype(env)::StepProgrammableToken tok_spec( &env );
5733+ tok_spec.callback = []( decltype(env)::LexingPoint& pt ) -> std::optional <eir::FixedString <char>>
5734+ {
5735+ const char *start_ptr = pt.GetCurrentData();
5736+
5737+ while ( pt.GetRemainder() > 0 )
5738+ {
5739+ char ucp = pt.ReadCharacter();
5740+
5741+ if ( !( ucp >= 'a' && ucp <= 'z' || ucp >= 'A' && ucp <= 'Z' || ucp == '_' ) )
5742+ {
5743+ pt.SetOffset( pt.GetOffset() - 1 );
5744+ break;
5745+ }
5746+ }
5747+
5748+ const char *end_ptr = pt.GetCurrentData();
5749+
5750+ size_t cnt = ( end_ptr - start_ptr );
5751+
5752+ if ( cnt == 0 )
5753+ return std::nullopt;
5754+
5755+ return eir::FixedString <char> ( start_ptr, cnt );
5756+ };
5757+
5758+ decltype(env)::StepAttribution spec_utype( &env );
5759+ spec_utype.SetNode( &tok_spec );
5760+ spec_utype.attribute_key = "utype";
5761+
5762+ decltype(env)::StepAttribution spec_name( &env );
5763+ spec_name.SetNode( &tok_spec );
5764+ spec_name.attribute_key = "name";
5765+
5766+ decltype(env)::StepToken tok_arrbeg( &env );
5767+ tok_arrbeg.token_str = "{";
5768+
5769+ decltype(env)::StepToken tok_arrend( &env );
5770+ tok_arrend.token_str = "}";
5771+
5772+ decltype(env)::StepProgrammableToken vspec( &env );
5773+ vspec.callback = []( decltype(env)::LexingPoint& pt ) -> std::optional <eir::FixedString <char>>
5774+ {
5775+ const char *start_ptr = pt.GetCurrentData();
5776+
5777+ while ( pt.GetRemainder() > 0 )
5778+ {
5779+ char ucp = pt.ReadCharacter();
5780+
5781+ if ( !( ucp >= 'a' && ucp <= 'z' || ucp >= 'A' && ucp <= 'Z' || ucp >= '0' && ucp <= '9' || ucp == '_' ) )
5782+ {
5783+ pt.SetOffset( pt.GetOffset() - 1 );
5784+ break;
5785+ }
5786+ }
5787+
5788+ const char *end_ptr = pt.GetCurrentData();
5789+
5790+ size_t cnt = ( end_ptr - start_ptr );
5791+
5792+ if ( cnt == 0 )
5793+ return std::nullopt;
5794+
5795+ return eir::FixedString <char> ( start_ptr, cnt );
5796+ };
5797+
5798+ decltype(env)::StepAttribution vspec_attrib_spec( &env );
5799+ vspec_attrib_spec.SetNode( &vspec );
5800+ vspec_attrib_spec.attribute_key = "spec";
5801+
5802+ struct valinit_builder
5803+ {
5804+ static inline void AssignAttributeTo( spec *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
5805+ {
5806+ assign_to->token = value;
5807+ }
5808+ };
5809+
5810+ decltype(env)::SerializedStep valinit_outer( &env );
5811+ valinit_outer.SetConnections( { &tok_arrbeg, &vspec_attrib_spec, &tok_arrend } );
5812+ valinit_outer.setSelector <direct_obj_build_selector <char, spec, node, valinit_builder, decltype(env)>> ( &env );
5813+
5814+ decltype(env)::StepAttribution valinit_inner( &env );
5815+ valinit_inner.SetNode( &vspec );
5816+ valinit_inner.attribute_key = "spec";
5817+ valinit_inner.setSelector <direct_obj_build_selector <char, spec, node, valinit_builder, decltype(env)>> ( &env );
5818+
5819+ decltype(env)::StepCustomIndirection init_expr( &env );
5820+ init_expr.attribute_key = "init";
5821+
5822+ decltype(env)::StepToken tok_comma( &env );
5823+ tok_comma.token_str = ",";
5824+
5825+ decltype(env)::StepSeparation sepinit( &env );
5826+ sepinit.SetItemStep( &init_expr );
5827+ sepinit.SetSeparationStep( &tok_comma );
5828+ sepinit.min_item_cnt = 0;
5829+ sepinit.is_alternation = false;
5830+ sepinit.attribute_key = "item";
5831+
5832+ struct arr_builder
5833+ {
5834+ static inline bool AssignNodeTo( arrnode *assign_to, const eir::FixedString <char>& attrib, node *n )
5835+ {
5836+ assign_to->items.AddToBack( n );
5837+ return true;
5838+ }
5839+ };
5840+
5841+ decltype(env)::SerializedStep arrinit( &env );
5842+ arrinit.SetConnections( { &tok_arrbeg, &sepinit, &tok_arrend } );
5843+ arrinit.setSelector <direct_obj_build_selector <char, arrnode, node, arr_builder, decltype(env)>> ( &env );
5844+
5845+ struct producible_selector
5846+ {
5847+ inline void AssignAttribute( const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
5848+ {
5849+ if ( attrib == "utype" )
5850+ {
5851+ this->type = new spec( value );
5852+ }
5853+ else if ( attrib == "loc" )
5854+ {
5855+ if ( value == "*" )
5856+ {
5857+ this->type = new ptrloc( this->type );
5858+ }
5859+ else if ( value == "&" )
5860+ {
5861+ this->type = new refloc( this->type );
5862+ }
5863+ }
5864+ else if ( attrib == "arrspec" )
5865+ {
5866+ this->type = new arrspec( this->type );
5867+ }
5868+ else if ( attrib == "name" )
5869+ {
5870+ this->name = new spec( value );
5871+ }
5872+ }
5873+
5874+ inline bool AssignNode( const eir::FixedString <char>& attrib, node *n )
5875+ {
5876+ if ( attrib == "init" )
5877+ {
5878+ this->init = n;
5879+ return true;
5880+ }
5881+
5882+ return false;
5883+ }
5884+
5885+ inline node* DetachFinishedNode( void )
5886+ {
5887+ return new decl( this->type, this->name, this->init );
5888+ }
5889+
5890+ node *type = nullptr;
5891+ node *name = nullptr;
5892+ node *init = nullptr;
5893+ };
5894+
5895+ decltype(env)::SerializedStep producible( &env );
5896+ producible.SetConnections( { &spec_utype, &locator, &spec_name, &reparrspec, &init_expr } );
5897+ producible.setSelector <producible_selector> ();
5898+
5899+ init_expr.callback = [&]( decltype(env)::ProductionMachine& machine ) -> decltype(env)::Step*
5900+ {
5901+ size_t prod_idx = machine.GetCurrentCalcStackMostRecentIndex( &producible );
5902+ size_t idx_below_cur = ( machine.GetCurrentCalcStackSize() - 1 );
5903+
5904+ // Returns the depth of this production.
5905+ size_t init_depth = 0;
5906+
5907+ for ( size_t n = prod_idx; n < idx_below_cur; n++ )
5908+ {
5909+ auto *s = machine.GetCurrentExecutionStepByIndex( n );
5910+
5911+ if ( s == &init_expr )
5912+ {
5913+ init_depth++;
5914+ }
5915+ }
5916+
5917+ producible_selector *prod_man = (producible_selector*)machine.GetCurrentExecutionSelectorDataByIndex( prod_idx );
5918+
5919+ node *type = prod_man->type;
5920+
5921+ size_t init_iter = init_depth;
5922+
5923+ while ( init_iter > 0 )
5924+ {
5925+ init_iter--;
5926+
5927+ if ( ptrloc *ploc = dynamic_cast <ptrloc*> ( type ) )
5928+ {
5929+ type = ploc->sub;
5930+ }
5931+ else if ( refloc *rloc = dynamic_cast <refloc*> ( type ) )
5932+ {
5933+ type = rloc->sub;
5934+ }
5935+ else if ( arrspec *as = dynamic_cast <arrspec*> ( type ) )
5936+ {
5937+ type = as->sub;
5938+ }
5939+ }
5940+
5941+ if ( dynamic_cast <arrspec*> ( type ) != nullptr )
5942+ {
5943+ return &arrinit;
5944+ }
5945+ else if ( init_depth > 0 )
5946+ {
5947+ return &valinit_inner;
5948+ }
5949+ else
5950+ {
5951+ return &valinit_outer;
5952+ }
5953+ };
5954+
5955+ decltype(env)::ProductionMachine machine( &env );
5956+
5957+ // 1)
5958+ machine.Execute( "int a[]{1,2,3}", &producible );
5959+
5960+ assert( machine.successful == true );
5961+ {
5962+ decl *root = dynamic_cast <decl*> ( machine.DetachNode() );
5963+
5964+ assert( root != nullptr );
5965+
5966+ arrspec *type = dynamic_cast <arrspec*> ( root->type );
5967+
5968+ assert( type != nullptr );
5969+
5970+ spec *type_sub = dynamic_cast <spec*> ( type->sub );
5971+
5972+ assert( type_sub != nullptr );
5973+ assert( type_sub->token == "int" );
5974+
5975+ type_sub->Delete();
5976+
5977+ type->Delete();
5978+
5979+ spec *name = dynamic_cast <spec*> ( root->name );
5980+
5981+ assert( name != nullptr );
5982+ assert( name->token == "a" );
5983+
5984+ name->Delete();
5985+
5986+ arrnode *init = dynamic_cast <arrnode*> ( root->init );
5987+
5988+ assert( init != nullptr );
5989+ assert( init->items.GetCount() == 3 );
5990+
5991+ spec *first = dynamic_cast <spec*> ( init->items[0] );
5992+ spec *second = dynamic_cast <spec*> ( init->items[1] );
5993+ spec *third = dynamic_cast <spec*> ( init->items[2] );
5994+
5995+ assert( first != nullptr );
5996+ assert( first->token == "1" );
5997+ assert( second != nullptr );
5998+ assert( second->token == "2" );
5999+ assert( third != nullptr );
6000+ assert( third->token == "3" );
6001+
6002+ first->Delete();
6003+ second->Delete();
6004+ third->Delete();
6005+
6006+ init->Delete();
6007+ root->Delete();
6008+ }
6009+
6010+ // 2)
6011+ machine.Execute( "int*b{nullptr}", &producible );
6012+
6013+ assert( machine.successful == true );
6014+ {
6015+ decl *root = dynamic_cast <decl*> ( machine.DetachNode() );
6016+
6017+ assert( root != nullptr );
6018+
6019+ ptrloc *type = dynamic_cast <ptrloc*> ( root->type );
6020+
6021+ assert( type != nullptr );
6022+
6023+ spec *type_sub = dynamic_cast <spec*> ( type->sub );
6024+
6025+ assert( type_sub != nullptr );
6026+ assert( type_sub->token == "int" );
6027+
6028+ type_sub->Delete();
6029+
6030+ type->Delete();
6031+
6032+ spec *name = dynamic_cast <spec*> ( root->name );
6033+
6034+ assert( name != nullptr );
6035+ assert( name->token == "b" );
6036+
6037+ name->Delete();
6038+
6039+ spec *first = dynamic_cast <spec*> ( root->init );
6040+
6041+ assert( first != nullptr );
6042+ assert( first->token == "nullptr" );
6043+
6044+ first->Delete();
6045+
6046+ root->Delete();
6047+ }
6048+
6049+ // 3)
6050+ machine.Execute( "int c[][]{{9,7},{},{1}}", &producible );
6051+
6052+ assert( machine.successful == true );
6053+ {
6054+ decl *root = dynamic_cast <decl*> ( machine.DetachNode() );
6055+
6056+ assert( root != nullptr );
6057+
6058+ arrspec *type = dynamic_cast <arrspec*> ( root->type );
6059+
6060+ assert( type != nullptr );
6061+
6062+ arrspec *type_sub = dynamic_cast <arrspec*> ( type->sub );
6063+
6064+ assert( type_sub != nullptr );
6065+
6066+ spec *type_sub_sub = dynamic_cast <spec*> ( type_sub->sub );
6067+
6068+ assert( type_sub_sub != nullptr );
6069+ assert( type_sub_sub->token == "int" );
6070+
6071+ type_sub_sub->Delete();
6072+
6073+ type_sub->Delete();
6074+ type->Delete();
6075+
6076+ spec *name = dynamic_cast <spec*> ( root->name );
6077+
6078+ assert( name != nullptr );
6079+ assert( name->token == "c" );
6080+
6081+ name->Delete();
6082+
6083+ arrnode *init = dynamic_cast <arrnode*> ( root->init );
6084+
6085+ assert( init != nullptr );
6086+ assert( init->items.GetCount() == 3 );
6087+
6088+ arrnode *init_first = dynamic_cast <arrnode*> ( init->items[0] );
6089+
6090+ assert( init_first != nullptr );
6091+ assert( init_first->items.GetCount() == 2 );
6092+
6093+ spec *init_first_first = dynamic_cast <spec*> ( init_first->items[0] );
6094+
6095+ assert( init_first_first != nullptr );
6096+ assert( init_first_first->token == "9" );
6097+
6098+ init_first_first->Delete();
6099+
6100+ spec *init_first_second = dynamic_cast <spec*> ( init_first->items[1] );
6101+
6102+ assert( init_first_second != nullptr );
6103+ assert( init_first_second->token == "7" );
6104+
6105+ init_first_second->Delete();
6106+
6107+ init_first->Delete();
6108+
6109+ arrnode *init_second = dynamic_cast <arrnode*> ( init->items[1] );
6110+
6111+ assert( init_second != nullptr );
6112+ assert( init_second->items.GetCount() == 0 );
6113+
6114+ init_second->Delete();
6115+
6116+ arrnode *init_third = dynamic_cast <arrnode*> ( init->items[2] );
6117+
6118+ assert( init_third != nullptr );
6119+ assert( init_third->items.GetCount() == 1 );
6120+
6121+ spec *init_third_first = dynamic_cast <spec*> ( init_third->items[0] );
6122+
6123+ assert( init_third_first != nullptr );
6124+ assert( init_third_first->token == "1" );
6125+
6126+ init_third_first->Delete();
6127+
6128+ init_third->Delete();
6129+ init->Delete();
6130+ root->Delete();
6131+ }
6132+
6133+ // 4)
6134+ machine.Execute( "int a{0}", &producible );
6135+
6136+ assert( machine.successful == true );
6137+ {
6138+ decl *root = dynamic_cast <decl*> ( machine.DetachNode() );
6139+
6140+ assert( root != nullptr );
6141+
6142+ spec *type = dynamic_cast <spec*> ( root->type );
6143+
6144+ assert( type != nullptr );
6145+ assert( type->token == "int" );
6146+
6147+ type->Delete();
6148+
6149+ spec *name = dynamic_cast <spec*> ( root->name );
6150+
6151+ assert( name != nullptr );
6152+ assert( name->token == "a" );
6153+
6154+ name->Delete();
6155+
6156+ spec *init = dynamic_cast <spec*> ( root->init );
6157+
6158+ assert( init != nullptr );
6159+ assert( init->token == "0" );
6160+
6161+ init->Delete();
6162+
6163+ root->Delete();
6164+ }
6165+
6166+ assert( _alive_node_count == 0 );
6167+ }
6168+ printf( "ok.\n" );
6169+
56186170 printf( "testing ProductionMachine mintwo-specialized-selector (simple list)..." );
56196171 {
56206172 struct Node
Show on old repository browser