• R/O
  • SSH
  • HTTPS

eircompile: Commit


Commit MetaInfo

Revision59 (tree)
Time2021-12-07 02:42:30
Authorquiret

Log Message

- added lexing_value_transgression_exception type which allows to pass lexical strings or nodes to upper-level, to nodes closer to the beginning node of a calculation path; useful for generalized classes that are reused among many lexed node classes, resharing code and tech
- added unit tests for lexing_value_transgression_exception throwing

Change Summary

Incremental Difference

--- eircompile/include/eircompile/lexing_env.h (revision 58)
+++ eircompile/include/eircompile/lexing_env.h (revision 59)
@@ -77,6 +77,7 @@
7777
7878 // Common lexing exceptions.
7979 struct lexing_invalid_parameter_exception {};
80+struct lexing_value_transgression_exception {};
8081
8182 #define LEXENV_TEMPLARGS \
8283 template <eir::CharacterType charType, LexerCompatibleNode <charType> cNodeType, eir::MemoryAllocator allocatorType = CRTHeapAllocator, LifetimeManager <cNodeType> lifetimeManType = NullLifetimeManager <cNodeType>>
@@ -2453,8 +2454,8 @@
24532454
24542455 if ( to_be_prefixed.IsEmpty() == false )
24552456 {
2456- to_be_prefixed.Insert( 0, eir::GetDotCharacter <charType> () );
2457- to_be_prefixed.Insert( 0, token.GetConstString(), token.GetLength() );
2457+ to_be_prefixed.Append( eir::GetDotCharacter <charType> () );
2458+ to_be_prefixed.Append( token.GetConstString(), token.GetLength() );
24582459 }
24592460 else
24602461 {
@@ -2472,6 +2473,11 @@
24722473 auto& to_be_prefixed = this->attrib_prefix;
24732474
24742475 size_t curlen = to_be_prefixed.GetLength();
2476+
2477+#ifdef _DEBUG
2478+ assert( toklen <= curlen );
2479+#endif //_DEBUG
2480+
24752481 curlen -= toklen;
24762482
24772483 // Remove the token.
@@ -2484,6 +2490,47 @@
24842490 }
24852491 }
24862492
2493+ inline void prependAttributeForDevolution( const eir::FixedString <charType>& token )
2494+ {
2495+ size_t token_len = token.GetLength();
2496+
2497+ if ( token_len == 0 )
2498+ return;
2499+
2500+ size_t prev_len = this->attrib_prefix.GetLength();
2501+
2502+ if ( prev_len == 0 )
2503+ {
2504+ this->attrib_prefix = token;
2505+ }
2506+ else
2507+ {
2508+ this->attrib_prefix.Insert( 0, eir::GetDotCharacter <charType> () );
2509+ this->attrib_prefix.Insert( 0, token.GetConstString(), token_len );
2510+ }
2511+ }
2512+
2513+ inline void unprependAttributeForDevolution( const eir::FixedString <charType>& token )
2514+ {
2515+ size_t token_len = token.GetLength();
2516+
2517+ if ( token_len == 0 )
2518+ return;
2519+
2520+ size_t prev_len = this->attrib_prefix.GetLength();
2521+
2522+ if ( prev_len == token_len )
2523+ {
2524+ this->attrib_prefix.Clear();
2525+ }
2526+ else
2527+ {
2528+ size_t rem_len = ( token_len + 1 ); // include the dot.
2529+
2530+ this->attrib_prefix.RemovePart( 0, rem_len );
2531+ }
2532+ }
2533+
24872534 inline node_selector* GetActiveSelector( void ) const
24882535 {
24892536 node_dispatcher *dispatch;
@@ -2525,6 +2572,10 @@
25252572 {
25262573 if ( node_selector *sel_man = GetActiveSelector() )
25272574 {
2575+#ifdef _DEBUG
2576+ assert( this->selectorMetaData_initialized == true );
2577+#endif //_DEBUG
2578+
25282579 sel_man->AssignAttribute( this->selectorMetaData, attrib, value );
25292580 }
25302581 }
@@ -2574,6 +2625,129 @@
25742625 void *selectorMetaData = nullptr; // if the assigned-to step has a node_selector, then this is used to hold its meta-data.
25752626 };
25762627
2628+ struct CalcPathDevolutionIterator
2629+ {
2630+ inline CalcPathDevolutionIterator( eir::Vector <CalcPathEntry, EnvironmentAllocator>& calc_stack_notop, CalcPathEntry& calc_stack_top ) noexcept : calc_stack_notop( calc_stack_notop ), calc_stack_top( calc_stack_top )
2631+ {
2632+ this->iter = &calc_stack_top;
2633+ }
2634+ inline CalcPathDevolutionIterator( const CalcPathDevolutionIterator& ) = delete;
2635+ inline CalcPathDevolutionIterator( CalcPathDevolutionIterator&& ) = delete;
2636+
2637+ inline ~CalcPathDevolutionIterator( void )
2638+ {
2639+ // Restore the default state of the calculation path/stack.
2640+ CalcPathEntry *iter = this->iter;
2641+
2642+ while ( iter != &this->calc_stack_top )
2643+ {
2644+ CalcPathEntry *prev_iter = iter;
2645+
2646+ // Actually put it to the top again.
2647+ size_t pn = ( iter - this->calc_stack_notop.GetData() );
2648+
2649+ if ( pn == this->calc_stack_notop.GetCount() - 1 )
2650+ {
2651+ iter = &this->calc_stack_top;
2652+ }
2653+ else
2654+ {
2655+ iter = ( iter + 1 );
2656+ }
2657+
2658+ // After incrementing we just restore the state that is supposed to exist.
2659+ iter->attrib_prefix = std::move( prev_iter->attrib_prefix );
2660+
2661+ if ( this->is_top_most_attrib_sequence == false && this->break_pt_iter == prev_iter )
2662+ {
2663+ this->is_top_most_attrib_sequence = true;
2664+ }
2665+
2666+ if ( this->is_top_most_attrib_sequence == false )
2667+ {
2668+ iter->unprependAttributeForDevolution( prev_iter->current_step->attribute_key.ToFixed() );
2669+ }
2670+ }
2671+ }
2672+
2673+ inline CalcPathEntry& GetCurrentEntry( void )
2674+ {
2675+ return *this->iter;
2676+ }
2677+
2678+ inline void Increment( void )
2679+ {
2680+ if ( this->calc_stack_notop.GetCount() == 0 )
2681+ {
2682+ this->iter = nullptr;
2683+ return;
2684+ }
2685+
2686+ CalcPathEntry *next_iter;
2687+ CalcPathEntry *prev_iter = this->iter;
2688+
2689+ advanceAgain:
2690+ if ( prev_iter == &this->calc_stack_top )
2691+ {
2692+ next_iter = &this->calc_stack_notop.GetBack();
2693+ }
2694+ else
2695+ {
2696+ size_t pn = ( prev_iter - this->calc_stack_notop.GetData() );
2697+
2698+ if ( pn == 0 )
2699+ {
2700+ this->iter = nullptr;
2701+ return;
2702+ }
2703+
2704+ next_iter = ( prev_iter - 1 );
2705+ }
2706+
2707+ // Devolve the path logic in the way down we go.
2708+ next_iter->attrib_prefix = std::move( prev_iter->attrib_prefix );
2709+
2710+ if ( this->is_top_most_attrib_sequence == false )
2711+ {
2712+ next_iter->prependAttributeForDevolution( prev_iter->current_step->attribute_key.ToFixed() );
2713+ }
2714+
2715+ // If we are to take the result from the above entry anyway, then we can skip the entry that will be the one that
2716+ // takes over anyway. This should be combined with the assumption that same types of nodes react compatibly-same
2717+ // to the acquisition of values.
2718+ if ( prev_iter->is_inline_call )
2719+ {
2720+ prev_iter = next_iter;
2721+ goto advanceAgain;
2722+ }
2723+
2724+ if ( this->is_top_most_attrib_sequence )
2725+ {
2726+ // We are past the top-most which was already built anyway.
2727+ this->is_top_most_attrib_sequence = false;
2728+
2729+ // Have to store data about when this break point happened.
2730+ this->break_pt_iter = next_iter;
2731+ }
2732+
2733+ this->iter = next_iter;
2734+ }
2735+
2736+ inline bool IsEnd( void ) const
2737+ {
2738+ return ( this->iter == nullptr );
2739+ }
2740+
2741+ private:
2742+ eir::Vector <CalcPathEntry, EnvironmentAllocator>& calc_stack_notop;
2743+ CalcPathEntry& calc_stack_top;
2744+
2745+ CalcPathEntry *iter;
2746+
2747+ bool is_top_most_attrib_sequence = true;
2748+ CalcPathEntry *break_pt_iter = nullptr;
2749+ };
2750+
25772751 enum class eBreakCondition
25782752 {
25792753 STEP_ENTER,
@@ -2905,10 +3079,9 @@
29053079 }
29063080 };
29073081
2908- auto catchup_stack_init = [&]( void )
3082+ auto _calcstack_init_at = [&]( size_t init_to_cnt, size_t calcstack_cnt )
29093083 {
2910- size_t calcstack_cnt = get_calcstack_size();
2911- size_t deepest_init_idx = calcstack_cnt;
3084+ size_t deepest_init_idx = init_to_cnt;
29123085
29133086 while ( deepest_init_idx > 0 )
29143087 {
@@ -2926,6 +3099,10 @@
29263099 for ( size_t iter = deepest_init_idx; iter < calcstack_cnt; iter++ )
29273100 {
29283101 CalcPathEntry& cur_ent = get_calcstack_idx( iter );
3102+
3103+ if ( cur_ent.requires_init == false )
3104+ break;
3105+
29293106 CalcPathEntry *prev_ent;
29303107
29313108 if ( iter > 0 )
@@ -2943,6 +3120,32 @@
29433120 }
29443121 };
29453122
3123+ auto catchup_stack_init = [&]( void )
3124+ {
3125+ size_t calcstack_cnt = get_calcstack_size();
3126+
3127+ return _calcstack_init_at( calcstack_cnt, calcstack_cnt );
3128+ };
3129+
3130+ auto calcstack_init_to_entry = [&]( CalcPathEntry& centry )
3131+ {
3132+ size_t calcstack_cnt = get_calcstack_size();
3133+
3134+ size_t init_to_cnt;
3135+
3136+ if ( &centry == &entry )
3137+ {
3138+ init_to_cnt = calcstack_cnt;
3139+ }
3140+ else
3141+ {
3142+ init_to_cnt = ( &centry - _calc_stack.GetData() );
3143+ init_to_cnt++;
3144+ }
3145+
3146+ _calcstack_init_at( init_to_cnt, calcstack_cnt );
3147+ };
3148+
29463149 entry.current_step = start_step;
29473150 entry.process_idx = 0;
29483151 entry.pt = buf;
@@ -3345,6 +3548,39 @@
33453548 // The user asked us to fail.
33463549 is_op_successful = false;
33473550 }
3551+ catch( lexing_value_transgression_exception& )
3552+ {
3553+ // Try to assign it to any node up the calculation path/closer to the beginning node.
3554+ CalcPathDevolutionIterator dev_iter( _calc_stack, entry );
3555+
3556+ tryNextValue:
3557+ // Skip the entry we already tried.
3558+ dev_iter.Increment();
3559+
3560+ if ( dev_iter.IsEnd() == false )
3561+ {
3562+ try
3563+ {
3564+ CalcPathEntry& maybe_entry = dev_iter.GetCurrentEntry();
3565+
3566+ // Make sure we initialize to this point.
3567+ calcstack_init_to_entry( maybe_entry );
3568+
3569+ auto& attrib_name = maybe_entry.attrib_prefix;
3570+
3571+ maybe_entry.AssignAttribute( attrib_name.ToFixed(), tkstep->token_str.ToFixed() );
3572+ }
3573+ catch( lexing_value_transgression_exception& )
3574+ {
3575+ goto tryNextValue;
3576+ }
3577+ }
3578+ else
3579+ {
3580+ // We failed to put in this value.
3581+ is_op_successful = false;
3582+ }
3583+ }
33483584 entry.debuildAttributePrefix( current_step->attribute_key.ToFixed() );
33493585 }
33503586 }
@@ -3381,6 +3617,39 @@
33813617 // Failure by user.
33823618 is_op_successful = false;
33833619 }
3620+ catch( lexing_value_transgression_exception& )
3621+ {
3622+ // Try to assign it to any node up the calculation path/closer to the beginning node.
3623+ CalcPathDevolutionIterator dev_iter( _calc_stack, entry );
3624+
3625+ tryNextValue2:
3626+ // Skip the entry we already tried.
3627+ dev_iter.Increment();
3628+
3629+ if ( dev_iter.IsEnd() == false )
3630+ {
3631+ try
3632+ {
3633+ CalcPathEntry& maybe_entry = dev_iter.GetCurrentEntry();
3634+
3635+ // Make sure we initialize to this point.
3636+ calcstack_init_to_entry( maybe_entry );
3637+
3638+ auto& attrib_name = maybe_entry.attrib_prefix;
3639+
3640+ maybe_entry.AssignAttribute( attrib_name.ToFixed(), restok.ToFixed() );
3641+ }
3642+ catch( lexing_value_transgression_exception& )
3643+ {
3644+ goto tryNextValue2;
3645+ }
3646+ }
3647+ else
3648+ {
3649+ // We failed to put in this value.
3650+ is_op_successful = false;
3651+ }
3652+ }
33843653 entry.debuildAttributePrefix( current_step->attribute_key.ToFixed() );
33853654 }
33863655 else
@@ -3875,7 +4144,7 @@
38754144 }
38764145 else
38774146 {
3878- // Just take over the node, if available.
4147+ // Take over just the node, if available.
38794148 cNodeType *resNode;
38804149
38814150 if ( prev_entry.requires_init )
@@ -3965,78 +4234,112 @@
39654234 {
39664235 catchup_stack_init();
39674236
3968- bool has_node = false;
3969- node_selector *sel_man = nullptr;
3970-
3971- if constexpr ( LexerStructHasAssignNode <cNodeType, charType, cNodeType> )
4237+ bool has_initialized_attrib_prefix = false;
4238+ //bool initialized_attrib_is_prev_already_capsulation;
39724239 {
3973- has_node = std::holds_alternative <cNodeType*> ( entry.pcalc );
3974- }
4240+ // Need to possibly also devolve down the calculation path.
4241+ CalcPathDevolutionIterator dev_iter( _calc_stack, entry );
39754242
3976- if ( has_node == false )
3977- {
3978- sel_man = entry.GetActiveSelector();
3979- }
4243+ tryNextNode3:
4244+ CalcPathEntry& assign_node_entry = dev_iter.GetCurrentEntry();
39804245
3981- bool has_selector = ( sel_man != nullptr );
4246+ // Make sure we initialize to this point.
4247+ calcstack_init_to_entry( assign_node_entry );
39824248
3983- if ( has_node || has_selector )
3984- {
3985- entry.appendAttributePrefix( current_step->attribute_key.ToFixed() );
3986- entry.appendAttributePrefix( prev_step->attribute_key.ToFixed() );
3987- try
4249+ bool has_node = false;
4250+ node_selector *sel_man = nullptr;
4251+
4252+ if constexpr ( LexerStructHasAssignNode <cNodeType, charType, cNodeType> )
39884253 {
3989- auto& attrib_name = entry.attrib_prefix;
4254+ has_node = std::holds_alternative <cNodeType*> ( assign_node_entry.pcalc );
4255+ }
39904256
3991- bool couldAssign;
4257+ if ( has_node == false )
4258+ {
4259+ sel_man = assign_node_entry.GetActiveSelector();
4260+ }
39924261
3993- if ( has_node )
4262+ bool has_selector = ( sel_man != nullptr );
4263+
4264+ if ( has_node || has_selector )
4265+ {
4266+ if ( !has_initialized_attrib_prefix )
39944267 {
3995- if constexpr ( LexerStructHasAssignNode <cNodeType, charType, cNodeType> )
4268+ entry.appendAttributePrefix( current_step->attribute_key.ToFixed() );
4269+ //entry.appendAttributePrefix( prev_step->attribute_key.ToFixed() );
4270+
4271+ has_initialized_attrib_prefix = true;
4272+ }
4273+
4274+ try
4275+ {
4276+ auto& attrib_name = assign_node_entry.attrib_prefix;
4277+
4278+ bool couldAssign;
4279+
4280+ if ( has_node )
39964281 {
3997- cNodeType *set_node = std::get <cNodeType*> ( entry.pcalc );
4282+ if constexpr ( LexerStructHasAssignNode <cNodeType, charType, cNodeType> )
4283+ {
4284+ cNodeType *set_node = std::get <cNodeType*> ( assign_node_entry.pcalc );
39984285
3999- couldAssign = set_node->AssignNode( attrib_name.ToFixed(), resNode );
4286+ couldAssign = set_node->AssignNode( attrib_name.ToFixed(), resNode );
4287+ }
4288+ else
4289+ {
4290+ couldAssign = false;
4291+ }
40004292 }
40014293 else
40024294 {
4003- couldAssign = false;
4295+ couldAssign = sel_man->AssignNode( assign_node_entry.selectorMetaData, attrib_name.ToFixed(), resNode );
40044296 }
4297+
4298+ if ( couldAssign )
4299+ {
4300+ // Since the node was successfully given into another node, it does not have to be
4301+ // added a reference count to.
4302+
4303+ resNode = nullptr;
4304+ }
40054305 }
4006- else
4306+ catch( lexing_invalid_parameter_exception& )
40074307 {
4008- couldAssign = sel_man->AssignNode( entry.selectorMetaData, attrib_name.ToFixed(), resNode );
4308+ // We have actually failed.
4309+ is_op_successful = false;
40094310 }
4010-
4011- if ( couldAssign )
4311+ catch( lexing_value_transgression_exception& )
40124312 {
4013- // Since the node was successfully given into another node, it does not have to be
4014- // added a reference count to.
4313+ // Have to try the next node, if not at the end of course.
4314+ dev_iter.Increment();
40154315
4016- resNode = nullptr;
4316+ if ( dev_iter.IsEnd() == false )
4317+ {
4318+ goto tryNextNode3;
4319+ }
40174320 }
40184321 }
4019- catch( lexing_invalid_parameter_exception& )
4322+ // If we are successful and there is no node in the previous step and the previous
4323+ // step is not ambiguous, then write the node as result.
4324+ else if ( current_step->IsUnambiguousCall() )
40204325 {
4021- // We have actually failed.
4022- is_op_successful = false;
4326+ bool has_assigned = assign_node_entry.ReplaceNode( resNode );
4327+
4328+ if ( has_assigned && resNode != nullptr )
4329+ {
4330+ // The node is now safe, so add a ref count to it.
4331+ this->env->lifetimeMan.AddRef( resNode );
4332+ }
4333+
4334+ resNode = nullptr;
40234335 }
4024- entry.debuildAttributePrefix( prev_step->attribute_key.ToFixed() );
4025- entry.debuildAttributePrefix( current_step->attribute_key.ToFixed() );
40264336 }
4027- // If we are successful and there is no node in the previous step and the previous
4028- // step is not ambiguous, then write the node as result.
4029- else if ( current_step->IsUnambiguousCall() )
4337+ // Now the iterator is destroyed and the calculation stack is in default and proper state.
4338+
4339+ if ( has_initialized_attrib_prefix )
40304340 {
4031- bool has_assigned = entry.ReplaceNode( resNode );
4032-
4033- if ( has_assigned && resNode != nullptr )
4034- {
4035- // The node is now safe, so add a ref count to it.
4036- this->env->lifetimeMan.AddRef( resNode );
4037- }
4038-
4039- resNode = nullptr;
4341+ //entry.debuildAttributePrefix( prev_step->attribute_key.ToFixed() );
4342+ entry.debuildAttributePrefix( current_step->attribute_key.ToFixed() );
40404343 }
40414344 }
40424345 catch( ... )
--- testcompiler/src/cos_tests.cpp (revision 58)
+++ testcompiler/src/cos_tests.cpp (revision 59)
@@ -306,31 +306,6 @@
306306 {
307307 };
308308
309-struct FunctionDefinition : public COSNode
310-{
311- inline FunctionDefinition( COSNode *return_type = nullptr, COSNode *name = nullptr, depVector <COSNode*> params = {}, COSNode *body = nullptr ) noexcept
312- : return_type( return_type ), name( name ), params( std::move( params ) ), body( body )
313- {
314- return;
315- }
316- inline FunctionDefinition( const FunctionDefinition& ) = default;
317- inline FunctionDefinition( FunctionDefinition&& right ) noexcept : params( std::move( right.params ) )
318- {
319- this->return_type = right.return_type;
320- this->name = right.name;
321- this->body = right.body;
322-
323- right.return_type = nullptr;
324- right.name = nullptr;
325- right.body = nullptr;
326- }
327-
328- COSNode *return_type;
329- COSNode *name;
330- depVector <COSNode*> params;
331- COSNode *body;
332-};
333-
334309 struct ReturnStatement : public COSNode
335310 {
336311 inline ReturnStatement( COSNode *op = nullptr ) noexcept : op( op )
@@ -551,7 +526,40 @@
551526
552527 COSNode *spec;
553528 };
529+struct RefTypeSpecifier : public COSNode
530+{
531+ inline RefTypeSpecifier( COSNode *spec = nullptr ) noexcept : spec( spec )
532+ {}
533+ inline RefTypeSpecifier( const RefTypeSpecifier& ) = default;
534+ inline RefTypeSpecifier( RefTypeSpecifier&& right ) noexcept
535+ {
536+ this->spec = right.spec;
554537
538+ right.spec = nullptr;
539+ }
540+
541+ COSNode *spec;
542+};
543+struct ArrayTypeSpecifier : public COSNode
544+{
545+ inline ArrayTypeSpecifier( COSNode *spec = nullptr, COSNode *array_size_op = nullptr ) noexcept : spec( spec ), array_size_op( array_size_op )
546+ {
547+ return;
548+ }
549+ inline ArrayTypeSpecifier( const ArrayTypeSpecifier& ) = default;
550+ inline ArrayTypeSpecifier( ArrayTypeSpecifier&& right ) noexcept
551+ {
552+ this->spec = right.spec;
553+ this->array_size_op = right.array_size_op;
554+
555+ right.spec = nullptr;
556+ right.array_size_op = nullptr;
557+ }
558+
559+ COSNode *spec;
560+ COSNode *array_size_op;
561+};
562+
555563 struct CurlyPack : public COSNode
556564 {
557565 inline CurlyPack( depVector <COSNode*> params = {} ) noexcept : params( std::move( params ) )
@@ -576,7 +584,22 @@
576584
577585 depVector <COSNode*> items;
578586 };
587+struct FuncsigDefinition : public COSNode
588+{
589+ inline FuncsigDefinition( COSNode *return_type = nullptr, depVector <COSNode*> params = {} ) noexcept : return_type( return_type ), params( std::move( params ) )
590+ {}
591+ inline FuncsigDefinition( const FuncsigDefinition& ) = default;
592+ inline FuncsigDefinition( FuncsigDefinition&& right ) noexcept : params( std::move( right.params ) )
593+ {
594+ this->return_type = right.return_type;
579595
596+ right.return_type = nullptr;
597+ }
598+
599+ COSNode *return_type;
600+ depVector <COSNode*> params;
601+};
602+
580603 }; // namespace COS
581604
582605 static inline bool is_num_nonzero( char c )
@@ -674,38 +697,7 @@
674697 };
675698 lexer.GetNamedProduction( "S" ).setSelector <mintwo_specialized_selector <char, Program, COSNode, program_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
676699 }
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 );
679- {
680- struct function_dispatcher
681- {
682- static inline bool AssignNodeTo( FunctionDefinition *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
683- {
684- if ( attrib == "type" )
685- {
686- assign_to->return_type = node;
687- return true;
688- }
689- else if ( attrib == "name" )
690- {
691- assign_to->name = node;
692- return true;
693- }
694- else if ( attrib == "param" )
695- {
696- assign_to->params.AddToBack( node );
697- return true;
698- }
699- else if ( attrib == "body" )
700- {
701- assign_to->body = node;
702- return true;
703- }
704- return false;
705- }
706- };
707- lexer.GetNamedProduction( "function" ).setSelector <direct_obj_build_selector <char, FunctionDefinition, COSNode, function_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
708- }
700+ assert( lexer.CompileProduction( compiler, "statement", "typedef | block | loop | if | except | objmod | takefirst multdecl spaces ';' | takefirst operation spaces ';'" ) == true );
709701 assert( lexer.CompileProduction( compiler, "paramlist", "[<0>param:declaration, spaces ',' spaces]" ) == true );
710702 assert( lexer.CompileProduction( compiler, "funcbody", "^!(block, <b> statement+funcstatement)" ) == true );
711703 assert( lexer.CompileProduction( compiler, "funcstatement", "\"return\" spaces (op:operation spaces)^0:1 ';'" ) == true );
@@ -741,26 +733,12 @@
741733 };
742734 lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, ResolveSpecifierOperation, COSNode, dynspec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
743735 }
744- assert( lexer.CompileProduction( compiler, "spec", "'*' spaces spec:spec" ) == true );
736+ assert( lexer.CompileProduction( compiler, "dtypedef", "\"typedef\" spaces tmultdecl spaces ';'" ) == true );
745737 {
746- struct ptr_spec_dispatcher
747- {
748- static inline bool AssignNodeTo( PointerTypeSpecifier *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
749- {
750- if ( attrib == "spec" )
751- {
752- assign_to->spec = node;
753- return true;
754- }
755- return false;
756- }
757- };
758- lexer.GetNamedProduction( "spec" ).GetLastStep()->setSelector <direct_obj_build_selector <char, PointerTypeSpecifier, COSNode, ptr_spec_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
759- }
760- assert( lexer.CompileProduction( compiler, "dtypedef", "\"typedef\" spaces srctype:spec spaces dsttype:spec spaces ';'" ) == true );
761- {
762738 struct typedef_dispatcher
763739 {
740+ // TODO: implement this statement after we have done the regular multdecl statement.
741+#if 0
764742 static inline bool AssignNodeTo( TypedefStatement *assign_to, const eir::FixedString <char>& attrib, COSNode *node )
765743 {
766744 if ( attrib == "srctype" )
@@ -775,8 +753,9 @@
775753 }
776754 return false;
777755 }
756+#endif //0
778757 };
779- lexer.GetNamedProduction( "dtypedef" ).setSelector <direct_obj_build_selector <char, TypedefStatement, COSNode, typedef_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
758+ //lexer.GetNamedProduction( "dtypedef" ).setSelector <direct_obj_build_selector <char, TypedefStatement, COSNode, typedef_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
780759 }
781760 assert( lexer.CompileProduction( compiler, "block", "'{' spaces [<0>statement:extended statement, spaces] spaces '}'" ) == true );
782761 {
@@ -1824,9 +1803,8 @@
18241803 }
18251804
18261805 // 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 );
1806+ assert( lexer.CompileProduction( compiler, "locator", "[<0>loc:'*',spaces] (spaces loc:'&')^0:1" ) == true );
1807+ assert( lexer.CompileProduction( compiler, "multdecl", "utype:spec spaces [locator spaces (funcsigdecl|locatedname) declinit, spaces ',' spaces]" ) == true );
18301808 {
18311809 struct declaratory_type_builder
18321810 {
@@ -1839,11 +1817,14 @@
18391817 COSNode *type;
18401818 };
18411819 }
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 );
1820+ assert( lexer.CompileProduction( compiler, "tmultdecl", "utype:spec spaces [locator spaces (funcsigdecl|locatedname), spaces ',' spaces]" ) == true );
1821+ assert( lexer.CompileProduction( compiler, "funcsigdecl", "isfunc:functag spaces '(' spaces locator spaces (subfunc:funcsigdecl|locatedname) spaces ')' spaces '(' spaces paramlist spaces ')'" ) == true );
1822+ {
1823+ // TODO.
1824+ }
1825+ assert( lexer.CompileProduction( compiler, "locatedname", "name:spec (spaces [arrspec:arrayspec, spaces])" ) == true );
18451826 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 );
1827+ assert( lexer.CompileProduction( compiler, "declaration", "utype:spec spaces locator spaces (funcsigdecl|locatedname) declinit" ) == true );
18471828 {
18481829 // TODO: adjust this to match the lexing capabilities.
18491830 struct declaration_dispatcher
@@ -1870,9 +1851,11 @@
18701851 };
18711852 lexer.GetNamedProduction( "declaration" ).setSelector <direct_obj_build_selector <char, DeclarationStatement, COSNode, declaration_dispatcher, decltype(lexer)::RuntimeEnv>> ( &lexer.GetRuntimeEnvironment() );
18721853 }
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 );
1854+ assert( lexer.CompileProduction( compiler, "typelocator", "[<0>arrspec:arrayspec, spaces]" ) == true );
1855+ assert( lexer.CompileProduction( compiler, "type", "utype:spec spaces locator spaces (typefuncsig|typelocator)" ) == true );
1856+ assert( lexer.CompileProduction( compiler, "typefuncsig", "isfunc:functag spaces ( '('spaces locator spaces (subfunc:typefuncsig|typelocator) spaces ')' spaces )^0:1 '(' spaces paramlist spaces ')'" ) == true );
1857+ assert( lexer.CompileProduction( compiler, "declinit", "( spaces '=' spaces init:operation | spaces init:curlypack )^0:1" ) == true );
1858+ assert( lexer.CompileProduction( compiler, "functag", "\"func\" | \"operator\" | \"proc\"" ) == true );
18761859
18771860 printf( "testing COS operations (non-deep)..." );
18781861 {
--- testcompiler/src/lexingenv_tests.cpp (revision 58)
+++ testcompiler/src/lexingenv_tests.cpp (revision 59)
@@ -6400,4 +6400,409 @@
64006400 root->Delete();
64016401 }
64026402 printf( "ok.\n" );
6403+
6404+ printf( "testing ProductionMachine lexical value transgression (string)..." );
6405+ {
6406+ // We can throw the lexical_value_transgression_exception to pass on lexical strings or nodes down the calculation stack/path.
6407+ // Doing so we can effectively extract data meant in a more generalized fashion into their proper containment.
6408+
6409+ struct node
6410+ {
6411+ virtual ~node( void )
6412+ {}
6413+
6414+ inline void Delete( void ) noexcept
6415+ {
6416+ delete this;
6417+ }
6418+ };
6419+
6420+ struct descriptor : public node
6421+ {
6422+ inline descriptor( depString <char> location = {}, node *data = nullptr ) noexcept : location( location ), data( data )
6423+ {}
6424+ inline descriptor( const descriptor& ) = default;
6425+ inline descriptor( descriptor&& right ) noexcept : location( std::move( right.location ) )
6426+ {
6427+ this->data = right.data;
6428+
6429+ right.data = nullptr;
6430+ }
6431+
6432+ depString <char> location; // name (string based)
6433+ node *data; // the recipe
6434+ };
6435+
6436+ struct recipe : public node
6437+ {
6438+ inline recipe( node *content = nullptr ) noexcept : content( content )
6439+ {}
6440+
6441+ node *content; // some content fluff.
6442+ };
6443+
6444+ struct content : public node
6445+ {};
6446+
6447+ LexingEnvironment <char, node, EirHeapLinkAllocator> env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
6448+
6449+ decltype(env)::StepToken tok_space( &env );
6450+ tok_space.token_str = " ";
6451+
6452+ decltype(env)::StepRepeatAny spaces( &env );
6453+ spaces.SetNode( &tok_space );
6454+
6455+ decltype(env)::StepToken recipe_content( &env );
6456+ recipe_content.token_str = "content";
6457+ recipe_content.setConstructor(
6458+ []
6459+ {
6460+ return new content();
6461+ }
6462+ );
6463+
6464+ decltype(env)::StepAttribution attr_recipe_content( &env );
6465+ attr_recipe_content.SetNode( &recipe_content );
6466+ attr_recipe_content.attribute_key = "content";
6467+
6468+ decltype(env)::StepToken tok_recipe_init( &env );
6469+ tok_recipe_init.token_str = "recipe";
6470+
6471+ decltype(env)::StepProgrammableToken tok_name( &env );
6472+ tok_name.callback = [&]( decltype(env)::LexingPoint& pt ) -> std::optional <eir::FixedString <char>>
6473+ {
6474+ const char *start_ptr = pt.GetCurrentData();
6475+
6476+ while ( pt.GetRemainder() > 0 )
6477+ {
6478+ char ucp = pt.ReadCharacter();
6479+
6480+ if ( !( ucp >= 'a' && ucp <= 'z' || ucp >= 'A' && ucp <= 'Z' || ucp >= '0' && ucp <= '9' || ucp == '_' ) )
6481+ {
6482+ pt.SetOffset( pt.GetOffset() - 1 );
6483+ break;
6484+ }
6485+ }
6486+
6487+ const char *end_ptr = pt.GetCurrentData();
6488+
6489+ size_t cnt = ( end_ptr - start_ptr );
6490+
6491+ if ( cnt == 0 )
6492+ return std::nullopt;
6493+
6494+ return eir::FixedString <char> ( start_ptr, cnt );
6495+ };
6496+
6497+ decltype(env)::StepAttribution location( &env );
6498+ location.SetNode( &tok_name );
6499+ location.attribute_key = "loc";
6500+
6501+ decltype(env)::StepToken tok_block_beg( &env );
6502+ tok_block_beg.token_str = "{";
6503+
6504+ decltype(env)::StepToken tok_block_end( &env );
6505+ tok_block_end.token_str = "}";
6506+
6507+ struct recipe_dispatcher
6508+ {
6509+ static inline void AssignAttributeTo( recipe *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
6510+ {
6511+ if ( attrib == "loc" )
6512+ {
6513+ // Pass it onto the descriptor.
6514+ throw lexing_value_transgression_exception();
6515+ }
6516+ }
6517+
6518+ static inline bool AssignNodeTo( recipe *assign_to, const eir::FixedString <char>& attrib, node *n )
6519+ {
6520+ if ( attrib == "content" )
6521+ {
6522+ assign_to->content = n;
6523+ return true;
6524+ }
6525+
6526+ return false;
6527+ }
6528+ };
6529+
6530+ decltype(env)::SerializedStep precipe( &env );
6531+ precipe.SetConnections( {
6532+ &tok_recipe_init,
6533+ &spaces,
6534+ &location,
6535+ &spaces,
6536+ &tok_block_beg,
6537+ &spaces,
6538+ &attr_recipe_content,
6539+ &spaces,
6540+ &tok_block_end
6541+ } );
6542+ precipe.setSelector <direct_obj_build_selector <char, recipe, node, recipe_dispatcher, decltype(env)>> ( &env );
6543+
6544+ struct descriptor_dispatcher
6545+ {
6546+ static inline void AssignAttributeTo( descriptor *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
6547+ {
6548+ if ( attrib == "loc" )
6549+ {
6550+ assign_to->location = value;
6551+ }
6552+ }
6553+
6554+ static inline bool AssignNodeTo( descriptor *assign_to, const eir::FixedString <char>& attrib, node *n )
6555+ {
6556+ assign_to->data = n;
6557+ return true;
6558+ }
6559+ };
6560+
6561+ decltype(env)::StepAlternatives pdescriptor( &env );
6562+ pdescriptor.AddConnection( &precipe );
6563+ pdescriptor.setSelector <direct_obj_build_selector <char, descriptor, node, descriptor_dispatcher, decltype(env)>> ( &env );
6564+
6565+ decltype(env)::ProductionMachine machine( &env );
6566+
6567+ // 1)
6568+ machine.Execute( "recipe rec { content }", &pdescriptor );
6569+
6570+ assert( machine.successful == true );
6571+ {
6572+ descriptor *root = dynamic_cast <descriptor*> ( machine.DetachNode() );
6573+
6574+ assert( root != nullptr );
6575+ assert( root->location == "rec" );
6576+
6577+ recipe *of = dynamic_cast <recipe*> ( root->data );
6578+
6579+ assert( of != nullptr );
6580+
6581+ content *of_description = dynamic_cast <content*> ( of->content );
6582+
6583+ assert( of_description != nullptr );
6584+
6585+ of_description->Delete();
6586+
6587+ of->Delete();
6588+ root->Delete();
6589+ }
6590+ }
6591+ printf( "ok.\n" );
6592+
6593+ printf( "testing ProductionMachine lexical value transgression (node)..." );
6594+ {
6595+ // We can throw the lexical_value_transgression_exception to pass on lexical strings or nodes down the calculation stack/path.
6596+ // Doing so we can effectively extract data meant in a more generalized fashion into their proper containment.
6597+
6598+ struct node
6599+ {
6600+ virtual ~node( void )
6601+ {}
6602+
6603+ inline void Delete( void ) noexcept
6604+ {
6605+ delete this;
6606+ }
6607+ };
6608+
6609+ struct specifier : public node
6610+ {
6611+ inline specifier( depString <char> str = {} ) noexcept : str( std::move( str ) )
6612+ {}
6613+ inline specifier( const specifier& ) = default;
6614+ inline specifier( specifier&& ) = default;
6615+
6616+ depString <char> str;
6617+ };
6618+
6619+ struct descriptor : public node
6620+ {
6621+ inline descriptor( node *location = nullptr, node *data = nullptr ) noexcept : location( location ), data( data )
6622+ {}
6623+ inline descriptor( const descriptor& ) = default;
6624+ inline descriptor( descriptor&& right ) noexcept
6625+ {
6626+ this->location = right.location;
6627+ this->data = right.data;
6628+
6629+ right.data = nullptr;
6630+ right.location = nullptr;
6631+ }
6632+
6633+ node *location; // name (node based)
6634+ node *data; // the recipe
6635+ };
6636+
6637+ struct recipe : public node
6638+ {
6639+ inline recipe( node *content = nullptr ) noexcept : content( content )
6640+ {}
6641+
6642+ node *content; // some content fluff.
6643+ };
6644+
6645+ struct content : public node
6646+ {};
6647+
6648+ LexingEnvironment <char, node, EirHeapLinkAllocator> env( eir::constr_with_alloc::DEFAULT, &globalHeapAlloc );
6649+
6650+ decltype(env)::StepToken tok_space( &env );
6651+ tok_space.token_str = " ";
6652+
6653+ decltype(env)::StepRepeatAny spaces( &env );
6654+ spaces.SetNode( &tok_space );
6655+
6656+ decltype(env)::StepToken recipe_content( &env );
6657+ recipe_content.token_str = "content";
6658+ recipe_content.setConstructor(
6659+ []
6660+ {
6661+ return new content();
6662+ }
6663+ );
6664+
6665+ decltype(env)::StepAttribution attr_recipe_content( &env );
6666+ attr_recipe_content.SetNode( &recipe_content );
6667+ attr_recipe_content.attribute_key = "content";
6668+
6669+ decltype(env)::StepToken tok_recipe_init( &env );
6670+ tok_recipe_init.token_str = "recipe";
6671+
6672+ decltype(env)::StepProgrammableToken tok_name( &env );
6673+ tok_name.callback = [&]( decltype(env)::LexingPoint& pt ) -> std::optional <eir::FixedString <char>>
6674+ {
6675+ const char *start_ptr = pt.GetCurrentData();
6676+
6677+ while ( pt.GetRemainder() > 0 )
6678+ {
6679+ char ucp = pt.ReadCharacter();
6680+
6681+ if ( !( ucp >= 'a' && ucp <= 'z' || ucp >= 'A' && ucp <= 'Z' || ucp >= '0' && ucp <= '9' || ucp == '_' ) )
6682+ {
6683+ pt.SetOffset( pt.GetOffset() - 1 );
6684+ break;
6685+ }
6686+ }
6687+
6688+ const char *end_ptr = pt.GetCurrentData();
6689+
6690+ size_t cnt = ( end_ptr - start_ptr );
6691+
6692+ if ( cnt == 0 )
6693+ return std::nullopt;
6694+
6695+ return eir::FixedString <char> ( start_ptr, cnt );
6696+ };
6697+ tok_name.attribute_key = "str";
6698+
6699+ struct specifier_dispatcher
6700+ {
6701+ static inline void AssignAttributeTo( specifier *assign_to, const eir::FixedString <char>& attrib, const eir::FixedString <char>& value )
6702+ {
6703+ if ( attrib == "str" )
6704+ {
6705+ assign_to->str = value;
6706+ }
6707+ }
6708+ };
6709+ tok_name.setSelector <direct_obj_build_selector <char, specifier, node, specifier_dispatcher, decltype(env)>> ( &env );
6710+
6711+ decltype(env)::StepAttribution location( &env );
6712+ location.SetNode( &tok_name );
6713+ location.attribute_key = "loc";
6714+
6715+ decltype(env)::StepToken tok_block_beg( &env );
6716+ tok_block_beg.token_str = "{";
6717+
6718+ decltype(env)::StepToken tok_block_end( &env );
6719+ tok_block_end.token_str = "}";
6720+
6721+ struct recipe_dispatcher
6722+ {
6723+ static inline bool AssignNodeTo( recipe *assign_to, const eir::FixedString <char>& attrib, node *n )
6724+ {
6725+ if ( attrib == "loc" )
6726+ {
6727+ // Pass it onto the descriptor.
6728+ throw lexing_value_transgression_exception();
6729+ }
6730+ if ( attrib == "content" )
6731+ {
6732+ assign_to->content = n;
6733+ return true;
6734+ }
6735+
6736+ return false;
6737+ }
6738+ };
6739+
6740+ decltype(env)::SerializedStep precipe( &env );
6741+ precipe.SetConnections( {
6742+ &tok_recipe_init,
6743+ &spaces,
6744+ &location,
6745+ &spaces,
6746+ &tok_block_beg,
6747+ &spaces,
6748+ &attr_recipe_content,
6749+ &spaces,
6750+ &tok_block_end
6751+ } );
6752+ precipe.setSelector <direct_obj_build_selector <char, recipe, node, recipe_dispatcher, decltype(env)>> ( &env );
6753+
6754+ struct descriptor_dispatcher
6755+ {
6756+ static inline bool AssignNodeTo( descriptor *assign_to, const eir::FixedString <char>& attrib, node *n )
6757+ {
6758+ if ( attrib == "loc" )
6759+ {
6760+ assign_to->location = n;
6761+ return true;
6762+ }
6763+ else
6764+ {
6765+ assign_to->data = n;
6766+ return true;
6767+ }
6768+ }
6769+ };
6770+
6771+ decltype(env)::StepAlternatives pdescriptor( &env );
6772+ pdescriptor.AddConnection( &precipe );
6773+ pdescriptor.setSelector <direct_obj_build_selector <char, descriptor, node, descriptor_dispatcher, decltype(env)>> ( &env );
6774+
6775+ decltype(env)::ProductionMachine machine( &env );
6776+
6777+ // 1)
6778+ machine.Execute( "recipe rec { content }", &pdescriptor );
6779+
6780+ assert( machine.successful == true );
6781+ {
6782+ descriptor *root = dynamic_cast <descriptor*> ( machine.DetachNode() );
6783+
6784+ assert( root != nullptr );
6785+
6786+ specifier *location = dynamic_cast <specifier*> ( root->location );
6787+
6788+ assert( location != nullptr );
6789+ assert( location->str == "rec" );
6790+
6791+ location->Delete();
6792+
6793+ recipe *of = dynamic_cast <recipe*> ( root->data );
6794+
6795+ assert( of != nullptr );
6796+
6797+ content *of_description = dynamic_cast <content*> ( of->content );
6798+
6799+ assert( of_description != nullptr );
6800+
6801+ of_description->Delete();
6802+
6803+ of->Delete();
6804+ root->Delete();
6805+ }
6806+ }
6807+ printf( "ok.\n" );
64036808 }
\ No newline at end of file
Show on old repository browser